diff --git a/app/src/main/cpp/ffmpeg/cmdutils.c b/app/src/main/cpp/ffmpeg/cmdutils.c index 9d31bbe..3f83e54 100644 --- a/app/src/main/cpp/ffmpeg/cmdutils.c +++ b/app/src/main/cpp/ffmpeg/cmdutils.c @@ -33,8 +33,10 @@ #include "compat/va_copy.h" #include "libavformat/avformat.h" #include "libavfilter/avfilter.h" -#include "libswresample/swresample.h" #include "libswscale/swscale.h" +#include "libswresample/swresample.h" +#include "libpostproc/postprocess.h" +#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" @@ -48,6 +50,7 @@ #include "libavutil/dict.h" #include "libavutil/opt.h" #include "libavutil/cpu.h" +#include "libavutil/ffversion.h" #include "libavutil/version.h" #include "cmdutils.h" #if CONFIG_NETWORK @@ -57,6 +60,9 @@ #include #include #endif +#ifdef _WIN32 +#include +#endif #include @@ -72,6 +78,12 @@ static FILE *report_file; static int report_file_level = AV_LOG_DEBUG; int hide_banner = 0; +enum show_muxdemuxers { + SHOW_DEFAULT, + SHOW_DEMUXERS, + SHOW_MUXERS, +}; + void init_opts(void) { av_dict_set(&sws_dict, "flags", "bicubic", 0); @@ -107,6 +119,15 @@ static void log_callback_report(void *ptr, int level, const char *fmt, va_list v } } +void init_dynload(void) +{ +#ifdef _WIN32 + /* Calling SetDllDirectory with the empty string (but not NULL) removes the + * current working directory from the DLL search path as a security pre-caution. */ + SetDllDirectory(""); +#endif +} + static void (*program_exit)(int ret); void register_exit(void (*cb)(int ret)) @@ -114,13 +135,12 @@ void register_exit(void (*cb)(int ret)) program_exit = cb; } -int exit_program(int ret) +void exit_program(int ret) { if (program_exit) program_exit(ret); longjmp(jump_buf, 1); - return ret; } double parse_number_or_die(const char *context, const char *numstr, int type, @@ -214,7 +234,6 @@ static const OptionDef *find_option(const OptionDef *po, const char *name) * by default. HAVE_COMMANDLINETOARGVW is true on cygwin, while * it doesn't provide the actual command line via GetCommandLineW(). */ #if HAVE_COMMANDLINETOARGVW && defined(_WIN32) -#include #include /* Will be leaked on exit */ static char** win32_argv_utf8 = NULL; @@ -864,28 +883,54 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) { "debug" , AV_LOG_DEBUG }, { "trace" , AV_LOG_TRACE }, }; + const char *token; char *tail; - int level; - int flags; - int i; - - flags = av_log_get_flags(); - tail = strstr(arg, "repeat"); - if (tail) - flags &= ~AV_LOG_SKIP_REPEATED; - else - flags |= AV_LOG_SKIP_REPEATED; - - av_log_set_flags(flags); - if (tail == arg) - arg += 6 + (arg[6]=='+'); - if(tail && !*arg) - return 0; + int flags = av_log_get_flags(); + int level = av_log_get_level(); + int cmd, i = 0; + + av_assert0(arg); + while (*arg) { + token = arg; + if (*token == '+' || *token == '-') { + cmd = *token++; + } else { + cmd = 0; + } + if (!i && !cmd) { + flags = 0; /* missing relative prefix, build absolute value */ + } + if (!strncmp(token, "repeat", 6)) { + if (cmd == '-') { + flags |= AV_LOG_SKIP_REPEATED; + } else { + flags &= ~AV_LOG_SKIP_REPEATED; + } + arg = token + 6; + } else if (!strncmp(token, "level", 5)) { + if (cmd == '-') { + flags &= ~AV_LOG_PRINT_LEVEL; + } else { + flags |= AV_LOG_PRINT_LEVEL; + } + arg = token + 5; + } else { + break; + } + i++; + } + if (!*arg) { + goto end; + } else if (*arg == '+') { + arg++; + } else if (!i) { + flags = av_log_get_flags(); /* level value without prefix, reset flags */ + } for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) { if (!strcmp(log_levels[i].name, arg)) { - av_log_set_level(log_levels[i].level); - return 0; + level = log_levels[i].level; + goto end; } } @@ -897,6 +942,9 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name); exit_program(1); } + +end: + av_log_set_flags(flags); av_log_set_level(level); return 0; } @@ -972,7 +1020,7 @@ static int init_report(const char *env) av_free(key); } - av_bprint_init(&filename, 0, 1); + av_bprint_init(&filename, 0, AV_BPRINT_SIZE_AUTOMATIC); expand_filename_template(&filename, av_x_if_null(filename_template, "%p-%t.log"), tm); av_free(filename_template); @@ -1086,15 +1134,21 @@ static void print_all_libs_info(int flags, int level) PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); PRINT_LIB_INFO(swscale, SWSCALE, flags, level); PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level); + PRINT_LIB_INFO(postproc, POSTPROC, flags, level); } static void print_program_info(int flags, int level) { const char *indent = flags & INDENT? " " : ""; + av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name); if (flags & SHOW_COPYRIGHT) + av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers", + program_birth_year, CONFIG_THIS_YEAR); av_log(NULL, level, "\n"); - av_log(NULL, level, FFMPEG_CONFIGURATION, indent); + av_log(NULL, level, "%sbuilt with %s\n", indent, CC_IDENT); + + av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent); } static void print_buildconf(int flags, int level) @@ -1232,10 +1286,12 @@ static int is_device(const AVClass *avclass) return AV_IS_INPUT_DEVICE(avclass->category) || AV_IS_OUTPUT_DEVICE(avclass->category); } -static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only) +static int show_formats_devices(void *optctx, const char *opt, const char *arg, int device_only, int muxdemuxers) { - AVInputFormat *ifmt = NULL; - AVOutputFormat *ofmt = NULL; + void *ifmt_opaque = NULL; + const AVInputFormat *ifmt = NULL; + void *ofmt_opaque = NULL; + const AVOutputFormat *ofmt = NULL; const char *last_name; int is_dev; @@ -1250,29 +1306,35 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, const char *name = NULL; const char *long_name = NULL; - while ((ofmt = av_oformat_next(ofmt))) { - is_dev = is_device(ofmt->priv_class); - if (!is_dev && device_only) - continue; - if ((!name || strcmp(ofmt->name, name) < 0) && - strcmp(ofmt->name, last_name) > 0) { - name = ofmt->name; - long_name = ofmt->long_name; - encode = 1; + if (muxdemuxers !=SHOW_DEMUXERS) { + ofmt_opaque = NULL; + while ((ofmt = av_muxer_iterate(&ofmt_opaque))) { + is_dev = is_device(ofmt->priv_class); + if (!is_dev && device_only) + continue; + if ((!name || strcmp(ofmt->name, name) < 0) && + strcmp(ofmt->name, last_name) > 0) { + name = ofmt->name; + long_name = ofmt->long_name; + encode = 1; + } } } - while ((ifmt = av_iformat_next(ifmt))) { - is_dev = is_device(ifmt->priv_class); - if (!is_dev && device_only) - continue; - if ((!name || strcmp(ifmt->name, name) < 0) && - strcmp(ifmt->name, last_name) > 0) { - name = ifmt->name; - long_name = ifmt->long_name; - encode = 0; + if (muxdemuxers != SHOW_MUXERS) { + ifmt_opaque = NULL; + while ((ifmt = av_demuxer_iterate(&ifmt_opaque))) { + is_dev = is_device(ifmt->priv_class); + if (!is_dev && device_only) + continue; + if ((!name || strcmp(ifmt->name, name) < 0) && + strcmp(ifmt->name, last_name) > 0) { + name = ifmt->name; + long_name = ifmt->long_name; + encode = 0; + } + if (name && strcmp(ifmt->name, name) == 0) + decode = 1; } - if (name && strcmp(ifmt->name, name) == 0) - decode = 1; } if (!name) break; @@ -1289,12 +1351,22 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg, int show_formats(void *optctx, const char *opt, const char *arg) { - return show_formats_devices(optctx, opt, arg, 0); + return show_formats_devices(optctx, opt, arg, 0, SHOW_DEFAULT); +} + +int show_muxers(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 0, SHOW_MUXERS); +} + +int show_demuxers(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 0, SHOW_DEMUXERS); } int show_devices(void *optctx, const char *opt, const char *arg) { - return show_formats_devices(optctx, opt, arg, 1); + return show_formats_devices(optctx, opt, arg, 1, SHOW_DEFAULT); } #define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \ @@ -1342,6 +1414,16 @@ static void print_codec(const AVCodec *c) AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_AUTO_THREADS)) printf("threads "); + if (c->capabilities & AV_CODEC_CAP_AVOID_PROBING) + printf("avoidprobe "); + if (c->capabilities & AV_CODEC_CAP_INTRA_ONLY) + printf("intraonly "); + if (c->capabilities & AV_CODEC_CAP_LOSSLESS) + printf("lossless "); + if (c->capabilities & AV_CODEC_CAP_HARDWARE) + printf("hardware "); + if (c->capabilities & AV_CODEC_CAP_HYBRID) + printf("hybrid "); if (!c->capabilities) printf("none"); printf("\n"); @@ -1362,6 +1444,17 @@ static void print_codec(const AVCodec *c) printf("\n"); } + if (avcodec_get_hw_config(c, 0)) { + printf(" Supported hardware devices: "); + for (int i = 0;; i++) { + const AVCodecHWConfig *config = avcodec_get_hw_config(c, i); + if (!config) + break; + printf("%s ", av_hwdevice_get_type_name(config->device_type)); + } + printf("\n"); + } + if (c->supported_framerates) { const AVRational *fps = c->supported_framerates; @@ -1560,10 +1653,11 @@ int show_encoders(void *optctx, const char *opt, const char *arg) int show_bsfs(void *optctx, const char *opt, const char *arg) { - AVBitStreamFilter *bsf = NULL; + const AVBitStreamFilter *bsf = NULL; + void *opaque = NULL; printf("Bitstream filters:\n"); - while ((bsf = av_bitstream_filter_next(bsf))) + while ((bsf = av_bsf_iterate(&opaque))) printf("%s\n", bsf->name); printf("\n"); return 0; @@ -1589,6 +1683,7 @@ int show_filters(void *optctx, const char *opt, const char *arg) #if CONFIG_AVFILTER const AVFilter *filter = NULL; char descr[64], *descr_cur; + void *opaque = NULL; int i, j; const AVFilterPad *pad; @@ -1600,7 +1695,7 @@ int show_filters(void *optctx, const char *opt, const char *arg) " V = Video input/output\n" " N = Dynamic number and/or type of input/output\n" " | = Source or sink filter\n"); - while ((filter = avfilter_next(filter))) { + while ((filter = av_filter_iterate(&opaque))) { descr_cur = descr; for (i = 0; i < 2; i++) { if (i) { @@ -1663,7 +1758,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) #endif while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { - enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(pix_desc); + enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc); printf("%c%c%c%c%c %-16s %d %2d\n", sws_isSupportedInput (pix_fmt) ? 'I' : '.', sws_isSupportedOutput(pix_fmt) ? 'O' : '.', @@ -1857,6 +1952,25 @@ static void show_help_filter(const char *name) } #endif +static void show_help_bsf(const char *name) +{ + const AVBitStreamFilter *bsf = av_bsf_get_by_name(name); + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No bitstream filter name specified.\n"); + return; + } else if (!bsf) { + av_log(NULL, AV_LOG_ERROR, "Unknown bit stream filter '%s'.\n", name); + return; + } + + printf("Bit stream filter %s\n", bsf->name); + PRINT_CODEC_SUPPORTED(bsf, codec_ids, enum AVCodecID, "codecs", + AV_CODEC_ID_NONE, GET_CODEC_NAME); + if (bsf->priv_class) + show_help_children(bsf->priv_class, AV_OPT_FLAG_BSF_PARAM); +} + int show_help(void *optctx, const char *opt, const char *arg) { char *topic, *par; @@ -1883,6 +1997,8 @@ int show_help(void *optctx, const char *opt, const char *arg) } else if (!strcmp(topic, "filter")) { show_help_filter(par); #endif + } else if (!strcmp(topic, "bsf")) { + show_help_bsf(par); } else { show_help_default(topic, par); } @@ -1974,7 +2090,7 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, codec = s->oformat ? avcodec_find_encoder(codec_id) : avcodec_find_decoder(codec_id); - switch (st->codec->codec_type) { + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: prefix = 'v'; flags |= AV_OPT_FLAG_VIDEO_PARAM; @@ -2032,7 +2148,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, return NULL; } for (i = 0; i < s->nb_streams; i++) - opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id, + opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, s, s->streams[i], NULL); return opts; } @@ -2058,18 +2174,10 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) double get_rotation(AVStream *st) { - AVDictionaryEntry *rotate_tag = av_dict_get(st->metadata, "rotate", NULL, 0); uint8_t* displaymatrix = av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, NULL); double theta = 0; - - if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) { - char *tail; - theta = av_strtod(rotate_tag->value, &tail); - if (*tail) - theta = 0; - } - if (displaymatrix && !theta) + if (displaymatrix) theta = -av_display_rotation_get((int32_t*) displaymatrix); theta -= 360*floor(theta/360 + 0.9/360); @@ -2092,7 +2200,7 @@ static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts) if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) return AVERROR(EINVAL); - printf("Audo-detected sources for %s:\n", fmt->name); + printf("Auto-detected sources for %s:\n", fmt->name); if (!fmt->get_device_list) { ret = AVERROR(ENOSYS); printf("Cannot list sources. Not implemented.\n"); @@ -2122,7 +2230,7 @@ static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts) if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) return AVERROR(EINVAL); - printf("Audo-detected sinks for %s:\n", fmt->name); + printf("Auto-detected sinks for %s:\n", fmt->name); if (!fmt->get_device_list) { ret = AVERROR(ENOSYS); printf("Cannot list sinks. Not implemented.\n"); diff --git a/app/src/main/cpp/ffmpeg/cmdutils.h b/app/src/main/cpp/ffmpeg/cmdutils.h index aa64ca9..6e2e0a2 100644 --- a/app/src/main/cpp/ffmpeg/cmdutils.h +++ b/app/src/main/cpp/ffmpeg/cmdutils.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef CMDUTILS_H -#define CMDUTILS_H +#ifndef FFTOOLS_CMDUTILS_H +#define FFTOOLS_CMDUTILS_H #include @@ -59,7 +59,12 @@ void register_exit(void (*cb)(int ret)); /** * Wraps exit with a program-specific cleanup routine. */ -int exit_program(int ret); +void exit_program(int ret) av_noreturn; + +/** + * Initialize dynamic library loading + */ +void init_dynload(void); /** * Initialize the cmdutils option system, in particular @@ -100,12 +105,6 @@ int opt_max_alloc(void *optctx, const char *opt, const char *arg); int opt_codec_debug(void *optctx, const char *opt, const char *arg); -#if CONFIG_OPENCL -int opt_opencl(void *optctx, const char *opt, const char *arg); - -int opt_opencl_bench(void *optctx, const char *opt, const char *arg); -#endif - /** * Limit the execution time. */ @@ -150,6 +149,7 @@ typedef struct SpecifierOpt { uint8_t *str; int i; int64_t i64; + uint64_t ui64; float f; double dbl; } u; @@ -201,6 +201,47 @@ typedef struct OptionDef { void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags, int alt_flags); +#if CONFIG_AVDEVICE +#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \ + { "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \ + "list sources of the input device", "device" }, \ + { "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks }, \ + "list sinks of the output device", "device" }, \ + +#else +#define CMDUTILS_COMMON_OPTIONS_AVDEVICE +#endif + +#define CMDUTILS_COMMON_OPTIONS \ + { "L", OPT_EXIT, { .func_arg = show_license }, "show license" }, \ + { "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "version", OPT_EXIT, { .func_arg = show_version }, "show version" }, \ + { "buildconf", OPT_EXIT, { .func_arg = show_buildconf }, "show build configuration" }, \ + { "formats", OPT_EXIT, { .func_arg = show_formats }, "show available formats" }, \ + { "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \ + { "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \ + { "devices", OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \ + { "codecs", OPT_EXIT, { .func_arg = show_codecs }, "show available codecs" }, \ + { "decoders", OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \ + { "encoders", OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \ + { "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \ + { "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" }, \ + { "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \ + { "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \ + { "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \ + { "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \ + { "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \ + { "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ + { "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ + { "report", 0, { (void*)opt_report }, "generate a report" }, \ + { "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \ + { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \ + { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \ + CMDUTILS_COMMON_OPTIONS_AVDEVICE \ + /** * Show help for all options with given flags in class and all its * children. @@ -436,6 +477,20 @@ int show_license(void *optctx, const char *opt, const char *arg); */ int show_formats(void *optctx, const char *opt, const char *arg); +/** + * Print a listing containing all the muxers supported by the + * program (including devices). + * This option processing function does not utilize the arguments. + */ +int show_muxers(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the demuxer supported by the + * program (including devices). + * This option processing function does not utilize the arguments. + */ +int show_demuxers(void *optctx, const char *opt, const char *arg); + /** * Print a listing containing all the devices supported by the * program. @@ -445,13 +500,13 @@ int show_devices(void *optctx, const char *opt, const char *arg); #if CONFIG_AVDEVICE /** - * Print a listing containing audodetected sinks of the output device. + * Print a listing containing autodetected sinks of the output device. * Device name with options may be passed as an argument to limit results. */ int show_sinks(void *optctx, const char *opt, const char *arg); /** - * Print a listing containing audodetected sources of the input device. + * Print a listing containing autodetected sources of the input device. * Device name with options may be passed as an argument to limit results. */ int show_sources(void *optctx, const char *opt, const char *arg); @@ -570,6 +625,9 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); +#define GET_CODEC_NAME(id)\ + const char *name = avcodec_descriptor_get(id)->name; + #define GET_SAMPLE_FMT_NAME(sample_fmt)\ const char *name = av_get_sample_fmt_name(sample_fmt) @@ -587,4 +645,4 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); double get_rotation(AVStream *st); -#endif /* CMDUTILS_H */ +#endif /* FFTOOLS_CMDUTILS_H */ diff --git a/app/src/main/cpp/ffmpeg/config.h b/app/src/main/cpp/ffmpeg/config.h index 993f706..d72abf6 100644 --- a/app/src/main/cpp/ffmpeg/config.h +++ b/app/src/main/cpp/ffmpeg/config.h @@ -1,8 +1,8 @@ /* Automatically generated by configure - do not modify! */ #ifndef FFMPEG_CONFIG_H #define FFMPEG_CONFIG_H -#define FFMPEG_CONFIGURATION "--target-os=linux --prefix=../ffmpeg-android/armeabi-v7a --enable-cross-compile --arch=arm --cc=/Users/xufulong/Library/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc --cross-prefix=/Users/xufulong/Library/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi- --sysroot=/Users/xufulong/Library/Android/android-ndk-r15c/platforms/android-21/arch-arm --enable-neon --enable-hwaccels --enable-static --disable-shared --disable-doc --enable-asm --enable-small --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-debug --enable-gpl --disable-avdevice --disable-indevs --disable-outdevs --disable-avresample --extra-cflags='-Os -fpic -march=armv7-a -mcpu=cortex-a8 -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb -I../ffmpeg-android/armeabi-v7a/include' --extra-ldflags='-lc -lm -ldl -llog -lgcc -lz -L../ffmpeg-android/armeabi-v7a/lib' --enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale --enable-avfilter --enable-network --enable-bsfs --enable-postproc --enable-filters --enable-encoders --enable-libmp3lame --enable-encoder=libmp3lame --enable-libx264 --enable-nonfree --disable-decoders --enable-decoder='mpeg4,h263,h264,flv,gif,hevc,vp9,wmv3,png,jpeg2000,mjpeg,mpeg2video,msmpeg4v2,msmpeg4v3,msvideo1,aac,aac_fixed,aac_latm,ac3,ac3_fixed,eac3,m4a,amrnb,amrwb,ape,dolby_e,vc1,flac,opus,vorbis,wmav2,mp3float,mp3,mp3adufloat,mp3adu,mp3on4float,mp3on4,pcm_alaw,pcm_dvd,pcm_f16le,pcm_f24le,pcm_f32be,pcm_f32le,pcm_f64be,pcm_f64le,pcm_s16be,pcm_s16le,pcm_s24be,pcm_s24le,pcm_s32be,pcm_s32le,pcm_s64be,pcm_s64le,pcm_mulaw,alac,adpcm_ms,pcm_u16be,pcm_u16le,pcm_u24be,pcm_u24le,pcm_u32be,pcm_u32le,pcm_vidc,pcm_zork,adpcm_ima_qt,adpcm_ima_wav' --enable-muxers --enable-parsers --enable-protocols --disable-demuxers --enable-demuxer='aac,ac3,alaw,amr,amrnb,amrwb,ape,asf,asf_o,avi,cavsvideo,codec2,concat,dnxhd,eac3,flac,flv,gif,gif_pipe,h263,h264,hevc,hls,image2,image2pipe,jpeg_pipe,lrc,m4v,matroska,webm,mjpeg,mov,mp4,m4a,3gp,mp3,mpeg,mpegts,mv,ogg,png_pipe,realtext,rm,rtp,rtsp,s16be,s16le,s24be,s24le,s32be,s32le,sdp,srt,swf,u16be,u16le,u24be,u24le,u32be,u32le,vc1,wav,webm_dash,manifest,xmv,f32be,f32le,f64be,f64le,mpegvideo,mulaw,sami,srt' --cpu=armv7-a" -#define FFMPEG_LICENSE "nonfree and unredistributable" +#define FFMPEG_CONFIGURATION "--target-os=linux --prefix=../ffmpeg-android/armeabi-v7a --enable-cross-compile --arch=arm --cc=/Users/xufulong/Library/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc --cross-prefix=/Users/xufulong/Library/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi- --sysroot=/Users/xufulong/Library/Android/android-ndk-r15c/platforms/android-21/arch-arm --enable-neon --enable-hwaccels --enable-static --disable-shared --disable-doc --enable-asm --enable-small --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-debug --enable-gpl --disable-avdevice --disable-indevs --disable-outdevs --disable-avresample --extra-cflags='-Os -fpic -march=armv7-a -mcpu=cortex-a8 -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb -I../ffmpeg-android/armeabi-v7a/include' --extra-ldflags='-lc -lm -ldl -llog -lgcc -lz -L../ffmpeg-android/armeabi-v7a/lib' --enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale --enable-avfilter --enable-network --enable-bsfs --enable-postproc --enable-filters --enable-encoders --enable-libmp3lame --enable-libx264 --enable-encoder='libmp3lame,libx264' --disable-decoders --enable-decoder='mjpeg,mpeg4,h263,h264,flv,hevc,wmv3,msmpeg4v3,msmpeg4v2,msvideo1,vc1,mpeg1video,mpeg2video,aac,ac3,ac3_fixed,m4a,amrnb,amrwb,vorbis,wmav2,dca,truehd,tscc,tscc2,dvvideo,msrle,cinepak,indeo5,hq_hqa,mp3float,mp3,mp3adufloat,mp3adu,mp3on4float,mp3on4,aac_fixed,aac_latm,eac3,png,wmav1,wmv1,wmv2,pcm_alaw,pcm_dvd,pcm_f16le,pcm_f24le,pcm_f32be,pcm_f32le,pcm_f64be,pcm_f64le,zlib,flac,opus,mlp,pcm_s16be,pcm_s16le,pcm_s24be,pcm_s24le,pcm_s32be,pcm_s32le,pcm_s64be,pcm_s64le,pcm_mulaw,alac,adpcm_ms,pcm_u16be,pcm_u16le,pcm_u24be,pcm_u24le,pcm_u32be,pcm_u32le,pcm_vidc,pcm_zork,adpcm_ima_qt,adpcm_ima_wav' --enable-muxers --enable-parsers --enable-protocols --disable-demuxers --enable-demuxer='aac,ac3,alaw,amr,amrnb,amrwb,ape,asf,asf_o,avi,cavsvideo,codec2,concat,dnxhd,eac3,flac,flv,gif,gif_pipe,h263,h264,hevc,hls,image2,image2pipe,jpeg_pipe,lrc,m4v,matroska,webm,mjpeg,mov,mp4,m4a,3gp,mp3,mpeg,mpegts,mv,ogg,png_pipe,realtext,rm,rtp,rtsp,s16be,s16le,s24be,s24le,s32be,s32le,sdp,srt,swf,u16be,u16le,u24be,u24le,u32be,u32le,vc1,wav,webm_dash,manifest,xmv,f32be,f32le,f64be,f64le,mpegvideo,mulaw,sami,srt' --cpu=armv7-a" +#define FFMPEG_LICENSE "GPL version 2 or later" #define CONFIG_THIS_YEAR 2019 #define FFMPEG_DATADIR "../ffmpeg-android/armeabi-v7a/share/ffmpeg" #define AVCONV_DATADIR "../ffmpeg-android/armeabi-v7a/share/ffmpeg" @@ -57,6 +57,7 @@ #define HAVE_AMD3DNOWEXT 0 #define HAVE_AVX 0 #define HAVE_AVX2 0 +#define HAVE_AVX512 0 #define HAVE_FMA3 0 #define HAVE_FMA4 0 #define HAVE_MMX 0 @@ -79,6 +80,7 @@ #define HAVE_MIPSDSP 0 #define HAVE_MIPSDSPR2 0 #define HAVE_MSA 0 +#define HAVE_MSA2 0 #define HAVE_LOONGSON2 0 #define HAVE_LOONGSON3 0 #define HAVE_MMI 0 @@ -101,6 +103,7 @@ #define HAVE_AMD3DNOWEXT_EXTERNAL 0 #define HAVE_AVX_EXTERNAL 0 #define HAVE_AVX2_EXTERNAL 0 +#define HAVE_AVX512_EXTERNAL 0 #define HAVE_FMA3_EXTERNAL 0 #define HAVE_FMA4_EXTERNAL 0 #define HAVE_MMX_EXTERNAL 0 @@ -123,6 +126,7 @@ #define HAVE_MIPSDSP_EXTERNAL 0 #define HAVE_MIPSDSPR2_EXTERNAL 0 #define HAVE_MSA_EXTERNAL 0 +#define HAVE_MSA2_EXTERNAL 0 #define HAVE_LOONGSON2_EXTERNAL 0 #define HAVE_LOONGSON3_EXTERNAL 0 #define HAVE_MMI_EXTERNAL 0 @@ -145,6 +149,7 @@ #define HAVE_AMD3DNOWEXT_INLINE 0 #define HAVE_AVX_INLINE 0 #define HAVE_AVX2_INLINE 0 +#define HAVE_AVX512_INLINE 0 #define HAVE_FMA3_INLINE 0 #define HAVE_FMA4_INLINE 0 #define HAVE_MMX_INLINE 0 @@ -167,6 +172,7 @@ #define HAVE_MIPSDSP_INLINE 0 #define HAVE_MIPSDSPR2_INLINE 0 #define HAVE_MSA_INLINE 0 +#define HAVE_MSA2_INLINE 0 #define HAVE_LOONGSON2_INLINE 0 #define HAVE_LOONGSON3_INLINE 0 #define HAVE_MMI_INLINE 0 @@ -174,35 +180,29 @@ #define HAVE_FAST_64BIT 0 #define HAVE_FAST_CLZ 1 #define HAVE_FAST_CMOV 0 -#define HAVE_LOCAL_ALIGNED_8 0 -#define HAVE_LOCAL_ALIGNED_16 0 -#define HAVE_LOCAL_ALIGNED_32 0 +#define HAVE_LOCAL_ALIGNED 0 #define HAVE_SIMD_ALIGN_16 1 -#define HAVE_ATOMICS_GCC 1 -#define HAVE_ATOMICS_SUNCC 0 -#define HAVE_ATOMICS_WIN32 0 +#define HAVE_SIMD_ALIGN_32 0 +#define HAVE_SIMD_ALIGN_64 0 #define HAVE_ATOMIC_CAS_PTR 0 -#define HAVE_ATOMIC_COMPARE_EXCHANGE 1 #define HAVE_MACHINE_RW_BARRIER 0 #define HAVE_MEMORYBARRIER 0 #define HAVE_MM_EMPTY 0 #define HAVE_RDTSC 0 -#define HAVE_SARESTART 1 #define HAVE_SEM_TIMEDWAIT 1 #define HAVE_SYNC_VAL_COMPARE_AND_SWAP 1 #define HAVE_CABS 0 #define HAVE_CEXP 0 #define HAVE_INLINE_ASM 1 #define HAVE_SYMVER 1 -#define HAVE_YASM 0 +#define HAVE_X86ASM 0 #define HAVE_BIGENDIAN 0 #define HAVE_FAST_UNALIGNED 1 -#define HAVE_ALSA_ASOUNDLIB_H 0 -#define HAVE_ALTIVEC_H 0 #define HAVE_ARPA_INET_H 1 #define HAVE_ASM_TYPES_H 1 #define HAVE_CDIO_PARANOIA_H 0 #define HAVE_CDIO_PARANOIA_PARANOIA_H 0 +#define HAVE_CUDA_H 0 #define HAVE_DISPATCH_DISPATCH_H 0 #define HAVE_DEV_BKTR_IOCTL_BT848_H 0 #define HAVE_DEV_BKTR_IOCTL_METEOR_H 0 @@ -211,25 +211,18 @@ #define HAVE_DEV_VIDEO_METEOR_IOCTL_METEOR_H 0 #define HAVE_DIRECT_H 0 #define HAVE_DIRENT_H 1 -#define HAVE_DLFCN_H 1 -#define HAVE_D3D11_H 0 +#define HAVE_DXGIDEBUG_H 0 #define HAVE_DXVA_H 0 #define HAVE_ES2_GL_H 0 #define HAVE_GSM_H 0 #define HAVE_IO_H 0 -#define HAVE_MACH_MACH_TIME_H 0 +#define HAVE_LINUX_PERF_EVENT_H 1 #define HAVE_MACHINE_IOCTL_BT848_H 0 #define HAVE_MACHINE_IOCTL_METEOR_H 0 #define HAVE_MALLOC_H 1 #define HAVE_OPENCV2_CORE_CORE_C_H 0 -#define HAVE_OPENJPEG_2_1_OPENJPEG_H 0 -#define HAVE_OPENJPEG_2_0_OPENJPEG_H 0 -#define HAVE_OPENJPEG_1_5_OPENJPEG_H 0 #define HAVE_OPENGL_GL3_H 0 #define HAVE_POLL_H 1 -#define HAVE_SNDIO_H 0 -#define HAVE_SOUNDCARD_H 0 -#define HAVE_SYS_MMAN_H 1 #define HAVE_SYS_PARAM_H 1 #define HAVE_SYS_RESOURCE_H 1 #define HAVE_SYS_SELECT_H 1 @@ -273,18 +266,20 @@ #define HAVE_SINF 1 #define HAVE_TRUNC 1 #define HAVE_TRUNCF 1 +#define HAVE_DOS_PATHS 0 +#define HAVE_LIBC_MSVCRT 0 +#define HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS 0 +#define HAVE_SECTION_DATA_REL_RO 1 +#define HAVE_THREADS 1 +#define HAVE_UWP 0 +#define HAVE_WINRT 0 #define HAVE_ACCESS 1 #define HAVE_ALIGNED_MALLOC 0 #define HAVE_ARC4RANDOM 1 #define HAVE_CLOCK_GETTIME 1 #define HAVE_CLOSESOCKET 0 #define HAVE_COMMANDLINETOARGVW 0 -#define HAVE_COTASKMEMFREE 0 -#define HAVE_CRYPTGENRANDOM 0 -#define HAVE_DLOPEN 1 #define HAVE_FCNTL 1 -#define HAVE_FLT_LIM 1 -#define HAVE_FORK 1 #define HAVE_GETADDRINFO 1 #define HAVE_GETHRTIME 0 #define HAVE_GETOPT 1 @@ -299,9 +294,7 @@ #define HAVE_GMTIME_R 1 #define HAVE_INET_ATON 1 #define HAVE_ISATTY 1 -#define HAVE_JACK_PORT_GET_LATENCY_RANGE 0 #define HAVE_KBHIT 0 -#define HAVE_LOADLIBRARY 0 #define HAVE_LOCALTIME_R 1 #define HAVE_LSTAT 1 #define HAVE_LZO1X_999_COMPRESS 0 @@ -316,6 +309,7 @@ #define HAVE_POSIX_MEMALIGN 1 #define HAVE_PTHREAD_CANCEL 0 #define HAVE_SCHED_GETAFFINITY 1 +#define HAVE_SECITEMIMPORT 0 #define HAVE_SETCONSOLETEXTATTRIBUTE 0 #define HAVE_SETCONSOLECTRLHANDLER 0 #define HAVE_SETMODE 0 @@ -328,15 +322,20 @@ #define HAVE_UTGETOSTYPEFROMSTRING 0 #define HAVE_VIRTUALALLOC 0 #define HAVE_WGLGETPROCADDRESS 0 +#define HAVE_BCRYPT 0 +#define HAVE_VAAPI_DRM 0 +#define HAVE_VAAPI_X11 0 +#define HAVE_VDPAU_X11 0 #define HAVE_PTHREADS 1 #define HAVE_OS2THREADS 0 #define HAVE_W32THREADS 0 +#define HAVE_AS_ARCH_DIRECTIVE 1 #define HAVE_AS_DN_DIRECTIVE 1 +#define HAVE_AS_FPU_DIRECTIVE 1 #define HAVE_AS_FUNC 1 #define HAVE_AS_OBJECT_ARCH 1 #define HAVE_ASM_MOD_Q 1 -#define HAVE_ATTRIBUTE_MAY_ALIAS 1 -#define HAVE_ATTRIBUTE_PACKED 1 +#define HAVE_BLOCKS_EXTENSION 0 #define HAVE_EBP_AVAILABLE 0 #define HAVE_EBX_AVAILABLE 0 #define HAVE_GNU_AS 1 @@ -352,7 +351,8 @@ #define HAVE_VFP_ARGS 0 #define HAVE_XFORM_ASM 0 #define HAVE_XMM_CLOBBERS 0 -#define HAVE_CONDITION_VARIABLE_PTR 0 +#define HAVE_KCMVIDEOCODECTYPE_HEVC 0 +#define HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE 0 #define HAVE_SOCKLEN_T 1 #define HAVE_STRUCT_ADDRINFO 1 #define HAVE_STRUCT_GROUP_SOURCE_REQ 1 @@ -367,38 +367,17 @@ #define HAVE_STRUCT_SOCKADDR_STORAGE 1 #define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 0 #define HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE 1 -#define HAVE_ATOMICS_NATIVE 1 -#define HAVE_DOS_PATHS 0 -#define HAVE_DXVA2_LIB 0 -#define HAVE_DXVA2API_COBJ 0 -#define HAVE_LIBC_MSVCRT 0 -#define HAVE_LIBDC1394_1 0 -#define HAVE_LIBDC1394_2 0 #define HAVE_MAKEINFO 1 #define HAVE_MAKEINFO_HTML 0 -#define HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS 0 +#define HAVE_OPENCL_D3D11 0 +#define HAVE_OPENCL_DRM_ARM 0 +#define HAVE_OPENCL_DRM_BEIGNET 0 +#define HAVE_OPENCL_DXVA2 0 +#define HAVE_OPENCL_VAAPI_BEIGNET 0 +#define HAVE_OPENCL_VAAPI_INTEL_MEDIA 0 #define HAVE_PERL 1 #define HAVE_POD2MAN 1 -#define HAVE_SDL2 0 -#define HAVE_SECTION_DATA_REL_RO 1 #define HAVE_TEXI2HTML 0 -#define HAVE_THREADS 1 -#define HAVE_VAAPI_DRM 0 -#define HAVE_VAAPI_X11 0 -#define HAVE_VDPAU_X11 0 -#define HAVE_WINRT 0 -#define HAVE_XLIB 0 -#define CONFIG_BSFS 1 -#define CONFIG_DECODERS 1 -#define CONFIG_ENCODERS 1 -#define CONFIG_HWACCELS 0 -#define CONFIG_PARSERS 1 -#define CONFIG_INDEVS 0 -#define CONFIG_OUTDEVS 0 -#define CONFIG_FILTERS 1 -#define CONFIG_DEMUXERS 1 -#define CONFIG_MUXERS 1 -#define CONFIG_PROTOCOLS 1 #define CONFIG_DOC 0 #define CONFIG_HTMLPAGES 0 #define CONFIG_MANPAGES 1 @@ -406,13 +385,17 @@ #define CONFIG_TXTPAGES 1 #define CONFIG_AVIO_DIR_CMD_EXAMPLE 1 #define CONFIG_AVIO_READING_EXAMPLE 1 -#define CONFIG_DECODING_ENCODING_EXAMPLE 1 +#define CONFIG_DECODE_AUDIO_EXAMPLE 1 +#define CONFIG_DECODE_VIDEO_EXAMPLE 1 #define CONFIG_DEMUXING_DECODING_EXAMPLE 1 +#define CONFIG_ENCODE_AUDIO_EXAMPLE 1 +#define CONFIG_ENCODE_VIDEO_EXAMPLE 1 #define CONFIG_EXTRACT_MVS_EXAMPLE 1 #define CONFIG_FILTER_AUDIO_EXAMPLE 1 #define CONFIG_FILTERING_AUDIO_EXAMPLE 1 #define CONFIG_FILTERING_VIDEO_EXAMPLE 1 #define CONFIG_HTTP_MULTICLIENT_EXAMPLE 1 +#define CONFIG_HW_DECODE_EXAMPLE 1 #define CONFIG_METADATA_EXAMPLE 1 #define CONFIG_MUXING_EXAMPLE 1 #define CONFIG_QSVDEC_EXAMPLE 0 @@ -421,27 +404,48 @@ #define CONFIG_SCALING_VIDEO_EXAMPLE 1 #define CONFIG_TRANSCODE_AAC_EXAMPLE 1 #define CONFIG_TRANSCODING_EXAMPLE 1 +#define CONFIG_VAAPI_ENCODE_EXAMPLE 0 +#define CONFIG_VAAPI_TRANSCODE_EXAMPLE 0 #define CONFIG_AVISYNTH 0 -#define CONFIG_BZLIB 0 -#define CONFIG_CHROMAPRINT 0 -#define CONFIG_CRYSTALHD 0 -#define CONFIG_DECKLINK 0 #define CONFIG_FREI0R 0 -#define CONFIG_GCRYPT 0 +#define CONFIG_LIBCDIO 0 +#define CONFIG_LIBDAVS2 0 +#define CONFIG_LIBRUBBERBAND 0 +#define CONFIG_LIBVIDSTAB 0 +#define CONFIG_LIBX264 1 +#define CONFIG_LIBX265 0 +#define CONFIG_LIBXAVS 0 +#define CONFIG_LIBXAVS2 0 +#define CONFIG_LIBXVID 0 +#define CONFIG_DECKLINK 0 +#define CONFIG_LIBFDK_AAC 0 +#define CONFIG_OPENSSL 0 +#define CONFIG_LIBTLS 0 #define CONFIG_GMP 0 +#define CONFIG_LIBARIBB24 0 +#define CONFIG_LIBLENSFUN 0 +#define CONFIG_LIBOPENCORE_AMRNB 0 +#define CONFIG_LIBOPENCORE_AMRWB 0 +#define CONFIG_LIBVMAF 0 +#define CONFIG_LIBVO_AMRWBENC 0 +#define CONFIG_MBEDTLS 0 +#define CONFIG_RKMPP 0 +#define CONFIG_LIBSMBCLIENT 0 +#define CONFIG_CHROMAPRINT 0 +#define CONFIG_GCRYPT 0 #define CONFIG_GNUTLS 0 -#define CONFIG_ICONV 0 #define CONFIG_JNI 0 #define CONFIG_LADSPA 0 +#define CONFIG_LIBAOM 0 #define CONFIG_LIBASS 0 #define CONFIG_LIBBLURAY 0 #define CONFIG_LIBBS2B 0 #define CONFIG_LIBCACA 0 -#define CONFIG_LIBCDIO 0 #define CONFIG_LIBCELT 0 +#define CONFIG_LIBCODEC2 0 +#define CONFIG_LIBDAV1D 0 #define CONFIG_LIBDC1394 0 -#define CONFIG_LIBEBUR128 0 -#define CONFIG_LIBFDK_AAC 0 +#define CONFIG_LIBDRM 0 #define CONFIG_LIBFLITE 0 #define CONFIG_LIBFONTCONFIG 0 #define CONFIG_LIBFREETYPE 0 @@ -450,77 +454,85 @@ #define CONFIG_LIBGSM 0 #define CONFIG_LIBIEC61883 0 #define CONFIG_LIBILBC 0 +#define CONFIG_LIBJACK 0 +#define CONFIG_LIBKLVANC 0 #define CONFIG_LIBKVAZAAR 0 #define CONFIG_LIBMODPLUG 0 #define CONFIG_LIBMP3LAME 1 -#define CONFIG_LIBNUT 0 -#define CONFIG_LIBOPENCORE_AMRNB 0 -#define CONFIG_LIBOPENCORE_AMRWB 0 +#define CONFIG_LIBMYSOFA 0 #define CONFIG_LIBOPENCV 0 #define CONFIG_LIBOPENH264 0 #define CONFIG_LIBOPENJPEG 0 #define CONFIG_LIBOPENMPT 0 #define CONFIG_LIBOPUS 0 #define CONFIG_LIBPULSE 0 +#define CONFIG_LIBRSVG 0 #define CONFIG_LIBRTMP 0 -#define CONFIG_LIBRUBBERBAND 0 -#define CONFIG_LIBSCHROEDINGER 0 #define CONFIG_LIBSHINE 0 #define CONFIG_LIBSMBCLIENT 0 #define CONFIG_LIBSNAPPY 0 #define CONFIG_LIBSOXR 0 #define CONFIG_LIBSPEEX 0 +#define CONFIG_LIBSRT 0 #define CONFIG_LIBSSH 0 +#define CONFIG_LIBTENSORFLOW 0 #define CONFIG_LIBTESSERACT 0 #define CONFIG_LIBTHEORA 0 #define CONFIG_LIBTWOLAME 0 #define CONFIG_LIBV4L2 0 -#define CONFIG_LIBVIDSTAB 0 -#define CONFIG_LIBVO_AMRWBENC 0 #define CONFIG_LIBVORBIS 0 #define CONFIG_LIBVPX 0 #define CONFIG_LIBWAVPACK 0 #define CONFIG_LIBWEBP 0 -#define CONFIG_LIBX264 1 -#define CONFIG_LIBX265 0 -#define CONFIG_LIBXAVS 0 -#define CONFIG_LIBXCB 0 -#define CONFIG_LIBXCB_SHM 0 -#define CONFIG_LIBXCB_SHAPE 0 -#define CONFIG_LIBXCB_XFIXES 0 -#define CONFIG_LIBXVID 0 +#define CONFIG_LIBXML2 0 #define CONFIG_LIBZIMG 0 #define CONFIG_LIBZMQ 0 #define CONFIG_LIBZVBI 0 -#define CONFIG_LZMA 0 +#define CONFIG_LV2 0 #define CONFIG_MEDIACODEC 0 -#define CONFIG_NETCDF 0 #define CONFIG_OPENAL 0 -#define CONFIG_OPENCL 0 #define CONFIG_OPENGL 0 -#define CONFIG_OPENSSL 0 +#define CONFIG_POCKETSPHINX 0 +#define CONFIG_VAPOURSYNTH 0 +#define CONFIG_ALSA 0 +#define CONFIG_APPKIT 0 +#define CONFIG_AVFOUNDATION 0 +#define CONFIG_BZLIB 0 +#define CONFIG_COREIMAGE 0 +#define CONFIG_ICONV 0 +#define CONFIG_LIBXCB 0 +#define CONFIG_LIBXCB_SHM 0 +#define CONFIG_LIBXCB_SHAPE 0 +#define CONFIG_LIBXCB_XFIXES 0 +#define CONFIG_LZMA 0 #define CONFIG_SCHANNEL 0 -#define CONFIG_SDL 0 #define CONFIG_SDL2 0 #define CONFIG_SECURETRANSPORT 0 -#define CONFIG_VIDEOTOOLBOX 0 -#define CONFIG_X11GRAB 0 +#define CONFIG_SNDIO 0 #define CONFIG_XLIB 0 #define CONFIG_ZLIB 1 +#define CONFIG_CUDA_NVCC 0 +#define CONFIG_CUDA_SDK 0 +#define CONFIG_LIBNPP 0 +#define CONFIG_LIBMFX 0 +#define CONFIG_MMAL 0 +#define CONFIG_OMX 0 +#define CONFIG_OPENCL 0 +#define CONFIG_AMF 0 #define CONFIG_AUDIOTOOLBOX 0 +#define CONFIG_CRYSTALHD 0 #define CONFIG_CUDA 0 +#define CONFIG_CUDA_LLVM 0 #define CONFIG_CUVID 0 #define CONFIG_D3D11VA 0 #define CONFIG_DXVA2 0 -#define CONFIG_LIBMFX 0 -#define CONFIG_LIBNPP 0 -#define CONFIG_MMAL 0 +#define CONFIG_FFNVCODEC 0 +#define CONFIG_NVDEC 0 #define CONFIG_NVENC 0 -#define CONFIG_OMX 0 #define CONFIG_VAAPI 0 -#define CONFIG_VDA 0 #define CONFIG_VDPAU 0 -#define CONFIG_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_VIDEOTOOLBOX 0 +#define CONFIG_V4L2_M2M 0 #define CONFIG_XVMC 0 #define CONFIG_FTRAPV 0 #define CONFIG_GRAY 0 @@ -533,20 +545,19 @@ #define CONFIG_STATIC 1 #define CONFIG_SWSCALE_ALPHA 1 #define CONFIG_GPL 1 -#define CONFIG_NONFREE 1 +#define CONFIG_NONFREE 0 #define CONFIG_VERSION3 0 -#define CONFIG_AVCODEC 1 #define CONFIG_AVDEVICE 0 #define CONFIG_AVFILTER 1 +#define CONFIG_SWSCALE 1 +#define CONFIG_POSTPROC 1 #define CONFIG_AVFORMAT 1 +#define CONFIG_AVCODEC 1 +#define CONFIG_SWRESAMPLE 1 #define CONFIG_AVRESAMPLE 0 #define CONFIG_AVUTIL 1 -#define CONFIG_POSTPROC 1 -#define CONFIG_SWRESAMPLE 1 -#define CONFIG_SWSCALE 1 #define CONFIG_FFPLAY 0 #define CONFIG_FFPROBE 0 -#define CONFIG_FFSERVER 0 #define CONFIG_FFMPEG 0 #define CONFIG_DCT 1 #define CONFIG_DWT 1 @@ -560,24 +571,44 @@ #define CONFIG_PIXELUTILS 1 #define CONFIG_NETWORK 1 #define CONFIG_RDFT 1 +#define CONFIG_AUTODETECT 0 #define CONFIG_FONTCONFIG 0 -#define CONFIG_MEMALIGN_HACK 0 +#define CONFIG_LINUX_PERF 1 #define CONFIG_MEMORY_POISONING 0 #define CONFIG_NEON_CLOBBER_TEST 0 +#define CONFIG_OSSFUZZ 0 #define CONFIG_PIC 1 -#define CONFIG_POD2MAN 1 -#define CONFIG_RAISE_MAJOR 0 #define CONFIG_THUMB 1 #define CONFIG_VALGRIND_BACKTRACE 0 #define CONFIG_XMM_CLOBBER_TEST 0 +#define CONFIG_BSFS 1 +#define CONFIG_DECODERS 1 +#define CONFIG_ENCODERS 1 +#define CONFIG_HWACCELS 0 +#define CONFIG_PARSERS 1 +#define CONFIG_INDEVS 0 +#define CONFIG_OUTDEVS 0 +#define CONFIG_FILTERS 1 +#define CONFIG_DEMUXERS 1 +#define CONFIG_MUXERS 1 +#define CONFIG_PROTOCOLS 1 #define CONFIG_AANDCTTABLES 1 #define CONFIG_AC3DSP 1 +#define CONFIG_ADTS_HEADER 1 #define CONFIG_AUDIO_FRAME_QUEUE 1 #define CONFIG_AUDIODSP 1 #define CONFIG_BLOCKDSP 1 #define CONFIG_BSWAPDSP 1 #define CONFIG_CABAC 1 +#define CONFIG_CBS 1 +#define CONFIG_CBS_AV1 1 +#define CONFIG_CBS_H264 1 +#define CONFIG_CBS_H265 1 +#define CONFIG_CBS_JPEG 0 +#define CONFIG_CBS_MPEG2 1 +#define CONFIG_CBS_VP9 1 #define CONFIG_DIRAC_PARSE 1 +#define CONFIG_DNN 1 #define CONFIG_DVPROFILE 1 #define CONFIG_EXIF 1 #define CONFIG_FAANDCT 1 @@ -592,29 +623,33 @@ #define CONFIG_H263DSP 1 #define CONFIG_H264CHROMA 1 #define CONFIG_H264DSP 1 +#define CONFIG_H264PARSE 1 #define CONFIG_H264PRED 1 #define CONFIG_H264QPEL 1 +#define CONFIG_HEVCPARSE 1 #define CONFIG_HPELDSP 1 #define CONFIG_HUFFMAN 1 #define CONFIG_HUFFYUVDSP 0 #define CONFIG_HUFFYUVENCDSP 1 #define CONFIG_IDCTDSP 1 #define CONFIG_IIRFILTER 1 -#define CONFIG_IMDCT15 1 +#define CONFIG_MDCT15 1 #define CONFIG_INTRAX8 1 #define CONFIG_ISO_MEDIA 1 -#define CONFIG_IVIDSP 0 +#define CONFIG_IVIDSP 1 #define CONFIG_JPEGTABLES 1 #define CONFIG_LGPLV3 0 #define CONFIG_LIBX262 0 -#define CONFIG_LLAUDDSP 1 -#define CONFIG_LLVIDDSP 1 +#define CONFIG_LLAUDDSP 0 +#define CONFIG_LLVIDDSP 0 +#define CONFIG_LLVIDENCDSP 1 #define CONFIG_LPC 1 #define CONFIG_LZF 0 #define CONFIG_ME_CMP 1 #define CONFIG_MPEG_ER 1 #define CONFIG_MPEGAUDIO 1 #define CONFIG_MPEGAUDIODSP 1 +#define CONFIG_MPEGAUDIOHEADER 1 #define CONFIG_MPEGVIDEO 1 #define CONFIG_MPEGVIDEOENC 1 #define CONFIG_MSS34DSP 0 @@ -623,12 +658,14 @@ #define CONFIG_QSV 0 #define CONFIG_QSVDEC 0 #define CONFIG_QSVENC 0 +#define CONFIG_QSVVPP 0 #define CONFIG_RANGECODER 1 #define CONFIG_RIFFDEC 1 #define CONFIG_RIFFENC 1 #define CONFIG_RTPDEC 1 #define CONFIG_RTPENC_CHAIN 1 #define CONFIG_RV34DSP 0 +#define CONFIG_SCENE_SAD 1 #define CONFIG_SINEWIN 1 #define CONFIG_SNAPPY 0 #define CONFIG_SRTP 1 @@ -636,38 +673,57 @@ #define CONFIG_TEXTUREDSP 0 #define CONFIG_TEXTUREDSPENC 0 #define CONFIG_TPELDSP 0 +#define CONFIG_VAAPI_1 0 #define CONFIG_VAAPI_ENCODE 0 #define CONFIG_VC1DSP 1 #define CONFIG_VIDEODSP 1 #define CONFIG_VP3DSP 0 #define CONFIG_VP56DSP 0 #define CONFIG_VP8DSP 0 -#define CONFIG_VT_BT2020 0 #define CONFIG_WMA_FREQS 1 #define CONFIG_WMV2DSP 1 #define CONFIG_AAC_ADTSTOASC_BSF 1 +#define CONFIG_AV1_FRAME_SPLIT_BSF 1 +#define CONFIG_AV1_METADATA_BSF 1 #define CONFIG_CHOMP_BSF 1 #define CONFIG_DUMP_EXTRADATA_BSF 1 #define CONFIG_DCA_CORE_BSF 1 +#define CONFIG_EAC3_CORE_BSF 1 +#define CONFIG_EXTRACT_EXTRADATA_BSF 1 +#define CONFIG_FILTER_UNITS_BSF 1 +#define CONFIG_H264_METADATA_BSF 1 #define CONFIG_H264_MP4TOANNEXB_BSF 1 +#define CONFIG_H264_REDUNDANT_PPS_BSF 1 +#define CONFIG_HAPQA_EXTRACT_BSF 1 +#define CONFIG_HEVC_METADATA_BSF 1 #define CONFIG_HEVC_MP4TOANNEXB_BSF 1 #define CONFIG_IMX_DUMP_HEADER_BSF 1 #define CONFIG_MJPEG2JPEG_BSF 1 #define CONFIG_MJPEGA_DUMP_HEADER_BSF 1 #define CONFIG_MP3_HEADER_DECOMPRESS_BSF 1 +#define CONFIG_MPEG2_METADATA_BSF 1 #define CONFIG_MPEG4_UNPACK_BFRAMES_BSF 1 #define CONFIG_MOV2TEXTSUB_BSF 1 #define CONFIG_NOISE_BSF 1 +#define CONFIG_NULL_BSF 1 +#define CONFIG_PRORES_METADATA_BSF 1 #define CONFIG_REMOVE_EXTRADATA_BSF 1 #define CONFIG_TEXT2MOVSUB_BSF 1 +#define CONFIG_TRACE_HEADERS_BSF 1 +#define CONFIG_TRUEHD_CORE_BSF 1 +#define CONFIG_VP9_METADATA_BSF 1 +#define CONFIG_VP9_RAW_REORDER_BSF 1 #define CONFIG_VP9_SUPERFRAME_BSF 1 +#define CONFIG_VP9_SUPERFRAME_SPLIT_BSF 1 #define CONFIG_AASC_DECODER 0 #define CONFIG_AIC_DECODER 0 #define CONFIG_ALIAS_PIX_DECODER 0 +#define CONFIG_AGM_DECODER 0 #define CONFIG_AMV_DECODER 0 #define CONFIG_ANM_DECODER 0 #define CONFIG_ANSI_DECODER 0 #define CONFIG_APNG_DECODER 0 +#define CONFIG_ARBC_DECODER 0 #define CONFIG_ASV1_DECODER 0 #define CONFIG_ASV2_DECODER 0 #define CONFIG_AURA_DECODER 0 @@ -680,6 +736,7 @@ #define CONFIG_BETHSOFTVID_DECODER 0 #define CONFIG_BFI_DECODER 0 #define CONFIG_BINK_DECODER 0 +#define CONFIG_BITPACKED_DECODER 0 #define CONFIG_BMP_DECODER 0 #define CONFIG_BMV_VIDEO_DECODER 0 #define CONFIG_BRENDER_PIX_DECODER 0 @@ -688,7 +745,8 @@ #define CONFIG_CDGRAPHICS_DECODER 0 #define CONFIG_CDXL_DECODER 0 #define CONFIG_CFHD_DECODER 0 -#define CONFIG_CINEPAK_DECODER 0 +#define CONFIG_CINEPAK_DECODER 1 +#define CONFIG_CLEARVIDEO_DECODER 0 #define CONFIG_CLJR_DECODER 0 #define CONFIG_CLLC_DECODER 0 #define CONFIG_COMFORTNOISE_DECODER 0 @@ -702,7 +760,7 @@ #define CONFIG_DPX_DECODER 0 #define CONFIG_DSICINVIDEO_DECODER 0 #define CONFIG_DVAUDIO_DECODER 0 -#define CONFIG_DVVIDEO_DECODER 0 +#define CONFIG_DVVIDEO_DECODER 1 #define CONFIG_DXA_DECODER 0 #define CONFIG_DXTORY_DECODER 0 #define CONFIG_DXV_DECODER 0 @@ -720,47 +778,56 @@ #define CONFIG_FFV1_DECODER 0 #define CONFIG_FFVHUFF_DECODER 0 #define CONFIG_FIC_DECODER 0 +#define CONFIG_FITS_DECODER 0 #define CONFIG_FLASHSV_DECODER 0 #define CONFIG_FLASHSV2_DECODER 0 #define CONFIG_FLIC_DECODER 0 #define CONFIG_FLV_DECODER 1 +#define CONFIG_FMVC_DECODER 0 #define CONFIG_FOURXM_DECODER 0 #define CONFIG_FRAPS_DECODER 0 #define CONFIG_FRWU_DECODER 0 #define CONFIG_G2M_DECODER 0 -#define CONFIG_GIF_DECODER 1 +#define CONFIG_GDV_DECODER 0 +#define CONFIG_GIF_DECODER 0 #define CONFIG_H261_DECODER 0 #define CONFIG_H263_DECODER 1 #define CONFIG_H263I_DECODER 0 #define CONFIG_H263P_DECODER 0 +#define CONFIG_H263_V4L2M2M_DECODER 0 #define CONFIG_H264_DECODER 1 #define CONFIG_H264_CRYSTALHD_DECODER 0 +#define CONFIG_H264_V4L2M2M_DECODER 0 #define CONFIG_H264_MEDIACODEC_DECODER 0 #define CONFIG_H264_MMAL_DECODER 0 #define CONFIG_H264_QSV_DECODER 0 -#define CONFIG_H264_VDA_DECODER 0 -#define CONFIG_H264_VDPAU_DECODER 0 +#define CONFIG_H264_RKMPP_DECODER 0 #define CONFIG_HAP_DECODER 0 #define CONFIG_HEVC_DECODER 1 #define CONFIG_HEVC_QSV_DECODER 0 +#define CONFIG_HEVC_RKMPP_DECODER 0 +#define CONFIG_HEVC_V4L2M2M_DECODER 0 #define CONFIG_HNM4_VIDEO_DECODER 0 -#define CONFIG_HQ_HQA_DECODER 0 +#define CONFIG_HQ_HQA_DECODER 1 #define CONFIG_HQX_DECODER 0 #define CONFIG_HUFFYUV_DECODER 0 +#define CONFIG_HYMT_DECODER 0 #define CONFIG_IDCIN_DECODER 0 #define CONFIG_IFF_ILBM_DECODER 0 +#define CONFIG_IMM4_DECODER 0 #define CONFIG_INDEO2_DECODER 0 #define CONFIG_INDEO3_DECODER 0 #define CONFIG_INDEO4_DECODER 0 -#define CONFIG_INDEO5_DECODER 0 +#define CONFIG_INDEO5_DECODER 1 #define CONFIG_INTERPLAY_VIDEO_DECODER 0 -#define CONFIG_JPEG2000_DECODER 1 +#define CONFIG_JPEG2000_DECODER 0 #define CONFIG_JPEGLS_DECODER 0 #define CONFIG_JV_DECODER 0 #define CONFIG_KGV1_DECODER 0 #define CONFIG_KMVC_DECODER 0 #define CONFIG_LAGARITH_DECODER 0 #define CONFIG_LOCO_DECODER 0 +#define CONFIG_LSCR_DECODER 0 #define CONFIG_M101_DECODER 0 #define CONFIG_MAGICYUV_DECODER 0 #define CONFIG_MDEC_DECODER 0 @@ -769,25 +836,26 @@ #define CONFIG_MJPEGB_DECODER 0 #define CONFIG_MMVIDEO_DECODER 0 #define CONFIG_MOTIONPIXELS_DECODER 0 -#define CONFIG_MPEG_XVMC_DECODER 0 -#define CONFIG_MPEG1VIDEO_DECODER 0 +#define CONFIG_MPEG1VIDEO_DECODER 1 #define CONFIG_MPEG2VIDEO_DECODER 1 #define CONFIG_MPEG4_DECODER 1 #define CONFIG_MPEG4_CRYSTALHD_DECODER 0 +#define CONFIG_MPEG4_V4L2M2M_DECODER 0 #define CONFIG_MPEG4_MMAL_DECODER 0 -#define CONFIG_MPEG4_VDPAU_DECODER 0 #define CONFIG_MPEGVIDEO_DECODER 0 -#define CONFIG_MPEG_VDPAU_DECODER 0 -#define CONFIG_MPEG1_VDPAU_DECODER 0 +#define CONFIG_MPEG1_V4L2M2M_DECODER 0 #define CONFIG_MPEG2_MMAL_DECODER 0 #define CONFIG_MPEG2_CRYSTALHD_DECODER 0 +#define CONFIG_MPEG2_V4L2M2M_DECODER 0 #define CONFIG_MPEG2_QSV_DECODER 0 +#define CONFIG_MPEG2_MEDIACODEC_DECODER 0 #define CONFIG_MSA1_DECODER 0 -#define CONFIG_MSMPEG4_CRYSTALHD_DECODER 0 +#define CONFIG_MSCC_DECODER 0 #define CONFIG_MSMPEG4V1_DECODER 0 #define CONFIG_MSMPEG4V2_DECODER 1 #define CONFIG_MSMPEG4V3_DECODER 1 -#define CONFIG_MSRLE_DECODER 0 +#define CONFIG_MSMPEG4_CRYSTALHD_DECODER 0 +#define CONFIG_MSRLE_DECODER 1 #define CONFIG_MSS1_DECODER 0 #define CONFIG_MSS2_DECODER 0 #define CONFIG_MSVIDEO1_DECODER 1 @@ -795,6 +863,7 @@ #define CONFIG_MTS2_DECODER 0 #define CONFIG_MVC1_DECODER 0 #define CONFIG_MVC2_DECODER 0 +#define CONFIG_MWSC_DECODER 0 #define CONFIG_MXPEG_DECODER 0 #define CONFIG_NUV_DECODER 0 #define CONFIG_PAF_VIDEO_DECODER 0 @@ -804,16 +873,19 @@ #define CONFIG_PGM_DECODER 0 #define CONFIG_PGMYUV_DECODER 0 #define CONFIG_PICTOR_DECODER 0 +#define CONFIG_PIXLET_DECODER 0 #define CONFIG_PNG_DECODER 1 #define CONFIG_PPM_DECODER 0 #define CONFIG_PRORES_DECODER 0 -#define CONFIG_PRORES_LGPL_DECODER 0 +#define CONFIG_PROSUMER_DECODER 0 +#define CONFIG_PSD_DECODER 0 #define CONFIG_PTX_DECODER 0 #define CONFIG_QDRAW_DECODER 0 #define CONFIG_QPEG_DECODER 0 #define CONFIG_QTRLE_DECODER 0 #define CONFIG_R10K_DECODER 0 #define CONFIG_R210_DECODER 0 +#define CONFIG_RASC_DECODER 0 #define CONFIG_RAWVIDEO_DECODER 0 #define CONFIG_RL2_DECODER 0 #define CONFIG_ROQ_DECODER 0 @@ -825,6 +897,7 @@ #define CONFIG_RV40_DECODER 0 #define CONFIG_S302M_DECODER 0 #define CONFIG_SANM_DECODER 0 +#define CONFIG_SCPR_DECODER 0 #define CONFIG_SCREENPRESSO_DECODER 0 #define CONFIG_SDX2_DPCM_DECODER 0 #define CONFIG_SGI_DECODER 0 @@ -835,6 +908,8 @@ #define CONFIG_SMVJPEG_DECODER 0 #define CONFIG_SNOW_DECODER 0 #define CONFIG_SP5X_DECODER 0 +#define CONFIG_SPEEDHQ_DECODER 0 +#define CONFIG_SRGC_DECODER 0 #define CONFIG_SUNRAST_DECODER 0 #define CONFIG_SVQ1_DECODER 0 #define CONFIG_SVQ3_DECODER 0 @@ -849,8 +924,8 @@ #define CONFIG_TRUEMOTION1_DECODER 0 #define CONFIG_TRUEMOTION2_DECODER 0 #define CONFIG_TRUEMOTION2RT_DECODER 0 -#define CONFIG_TSCC_DECODER 0 -#define CONFIG_TSCC2_DECODER 0 +#define CONFIG_TSCC_DECODER 1 +#define CONFIG_TSCC2_DECODER 1 #define CONFIG_TXD_DECODER 0 #define CONFIG_ULTI_DECODER 0 #define CONFIG_UTVIDEO_DECODER 0 @@ -863,28 +938,34 @@ #define CONFIG_VBLE_DECODER 0 #define CONFIG_VC1_DECODER 1 #define CONFIG_VC1_CRYSTALHD_DECODER 0 -#define CONFIG_VC1_VDPAU_DECODER 0 #define CONFIG_VC1IMAGE_DECODER 0 #define CONFIG_VC1_MMAL_DECODER 0 #define CONFIG_VC1_QSV_DECODER 0 +#define CONFIG_VC1_V4L2M2M_DECODER 0 #define CONFIG_VCR1_DECODER 0 #define CONFIG_VMDVIDEO_DECODER 0 #define CONFIG_VMNC_DECODER 0 #define CONFIG_VP3_DECODER 0 +#define CONFIG_VP4_DECODER 0 #define CONFIG_VP5_DECODER 0 #define CONFIG_VP6_DECODER 0 #define CONFIG_VP6A_DECODER 0 #define CONFIG_VP6F_DECODER 0 #define CONFIG_VP7_DECODER 0 #define CONFIG_VP8_DECODER 0 -#define CONFIG_VP9_DECODER 1 +#define CONFIG_VP8_RKMPP_DECODER 0 +#define CONFIG_VP8_V4L2M2M_DECODER 0 +#define CONFIG_VP9_DECODER 0 +#define CONFIG_VP9_RKMPP_DECODER 0 +#define CONFIG_VP9_V4L2M2M_DECODER 0 #define CONFIG_VQA_DECODER 0 #define CONFIG_WEBP_DECODER 0 -#define CONFIG_WMV1_DECODER 0 -#define CONFIG_WMV2_DECODER 0 +#define CONFIG_WCMV_DECODER 0 +#define CONFIG_WRAPPED_AVFRAME_DECODER 0 +#define CONFIG_WMV1_DECODER 1 +#define CONFIG_WMV2_DECODER 1 #define CONFIG_WMV3_DECODER 1 #define CONFIG_WMV3_CRYSTALHD_DECODER 0 -#define CONFIG_WMV3_VDPAU_DECODER 0 #define CONFIG_WMV3IMAGE_DECODER 0 #define CONFIG_WNV1_DECODER 0 #define CONFIG_XAN_WC3_DECODER 0 @@ -892,6 +973,7 @@ #define CONFIG_XBM_DECODER 0 #define CONFIG_XFACE_DECODER 0 #define CONFIG_XL_DECODER 0 +#define CONFIG_XPM_DECODER 0 #define CONFIG_XWD_DECODER 0 #define CONFIG_Y41P_DECODER 0 #define CONFIG_YLC_DECODER 0 @@ -899,7 +981,7 @@ #define CONFIG_YUV4_DECODER 0 #define CONFIG_ZERO12V_DECODER 0 #define CONFIG_ZEROCODEC_DECODER 0 -#define CONFIG_ZLIB_DECODER 0 +#define CONFIG_ZLIB_DECODER 1 #define CONFIG_ZMBV_DECODER 0 #define CONFIG_AAC_DECODER 1 #define CONFIG_AAC_FIXED_DECODER 1 @@ -910,15 +992,21 @@ #define CONFIG_ALS_DECODER 0 #define CONFIG_AMRNB_DECODER 1 #define CONFIG_AMRWB_DECODER 1 -#define CONFIG_APE_DECODER 1 +#define CONFIG_APE_DECODER 0 +#define CONFIG_APTX_DECODER 0 +#define CONFIG_APTX_HD_DECODER 0 #define CONFIG_ATRAC1_DECODER 0 #define CONFIG_ATRAC3_DECODER 0 +#define CONFIG_ATRAC3AL_DECODER 0 #define CONFIG_ATRAC3P_DECODER 0 +#define CONFIG_ATRAC3PAL_DECODER 0 +#define CONFIG_ATRAC9_DECODER 0 #define CONFIG_BINKAUDIO_DCT_DECODER 0 #define CONFIG_BINKAUDIO_RDFT_DECODER 0 #define CONFIG_BMV_AUDIO_DECODER 0 #define CONFIG_COOK_DECODER 0 -#define CONFIG_DCA_DECODER 0 +#define CONFIG_DCA_DECODER 1 +#define CONFIG_DOLBY_E_DECODER 0 #define CONFIG_DSD_LSBF_DECODER 0 #define CONFIG_DSD_MSBF_DECODER 0 #define CONFIG_DSD_LSBF_PLANAR_DECODER 0 @@ -934,23 +1022,25 @@ #define CONFIG_G729_DECODER 0 #define CONFIG_GSM_DECODER 0 #define CONFIG_GSM_MS_DECODER 0 +#define CONFIG_HCOM_DECODER 0 #define CONFIG_IAC_DECODER 0 +#define CONFIG_ILBC_DECODER 0 #define CONFIG_IMC_DECODER 0 #define CONFIG_INTERPLAY_ACM_DECODER 0 #define CONFIG_MACE3_DECODER 0 #define CONFIG_MACE6_DECODER 0 #define CONFIG_METASOUND_DECODER 0 -#define CONFIG_MLP_DECODER 0 +#define CONFIG_MLP_DECODER 1 #define CONFIG_MP1_DECODER 0 #define CONFIG_MP1FLOAT_DECODER 0 #define CONFIG_MP2_DECODER 0 #define CONFIG_MP2FLOAT_DECODER 0 -#define CONFIG_MP3_DECODER 1 #define CONFIG_MP3FLOAT_DECODER 1 -#define CONFIG_MP3ADU_DECODER 1 +#define CONFIG_MP3_DECODER 1 #define CONFIG_MP3ADUFLOAT_DECODER 1 -#define CONFIG_MP3ON4_DECODER 1 +#define CONFIG_MP3ADU_DECODER 1 #define CONFIG_MP3ON4FLOAT_DECODER 1 +#define CONFIG_MP3ON4_DECODER 1 #define CONFIG_MPC7_DECODER 0 #define CONFIG_MPC8_DECODER 0 #define CONFIG_NELLYMOSER_DECODER 0 @@ -959,15 +1049,17 @@ #define CONFIG_PAF_AUDIO_DECODER 0 #define CONFIG_QCELP_DECODER 0 #define CONFIG_QDM2_DECODER 0 +#define CONFIG_QDMC_DECODER 0 #define CONFIG_RA_144_DECODER 0 #define CONFIG_RA_288_DECODER 0 #define CONFIG_RALF_DECODER 0 +#define CONFIG_SBC_DECODER 0 #define CONFIG_SHORTEN_DECODER 0 #define CONFIG_SIPR_DECODER 0 #define CONFIG_SMACKAUD_DECODER 0 #define CONFIG_SONIC_DECODER 0 #define CONFIG_TAK_DECODER 0 -#define CONFIG_TRUEHD_DECODER 0 +#define CONFIG_TRUEHD_DECODER 1 #define CONFIG_TRUESPEECH_DECODER 0 #define CONFIG_TTA_DECODER 0 #define CONFIG_TWINVQ_DECODER 0 @@ -976,7 +1068,7 @@ #define CONFIG_WAVPACK_DECODER 0 #define CONFIG_WMALOSSLESS_DECODER 0 #define CONFIG_WMAPRO_DECODER 0 -#define CONFIG_WMAV1_DECODER 0 +#define CONFIG_WMAV1_DECODER 1 #define CONFIG_WMAV2_DECODER 1 #define CONFIG_WMAVOICE_DECODER 0 #define CONFIG_WS_SND1_DECODER 0 @@ -985,6 +1077,8 @@ #define CONFIG_PCM_ALAW_DECODER 1 #define CONFIG_PCM_BLURAY_DECODER 0 #define CONFIG_PCM_DVD_DECODER 1 +#define CONFIG_PCM_F16LE_DECODER 1 +#define CONFIG_PCM_F24LE_DECODER 1 #define CONFIG_PCM_F32BE_DECODER 1 #define CONFIG_PCM_F32LE_DECODER 1 #define CONFIG_PCM_F64BE_DECODER 1 @@ -1013,7 +1107,9 @@ #define CONFIG_PCM_U24LE_DECODER 1 #define CONFIG_PCM_U32BE_DECODER 1 #define CONFIG_PCM_U32LE_DECODER 1 +#define CONFIG_PCM_VIDC_DECODER 1 #define CONFIG_PCM_ZORK_DECODER 1 +#define CONFIG_GREMLIN_DPCM_DECODER 0 #define CONFIG_INTERPLAY_DPCM_DECODER 0 #define CONFIG_ROQ_DPCM_DECODER 0 #define CONFIG_SOL_DPCM_DECODER 0 @@ -1021,6 +1117,7 @@ #define CONFIG_ADPCM_4XM_DECODER 0 #define CONFIG_ADPCM_ADX_DECODER 0 #define CONFIG_ADPCM_AFC_DECODER 0 +#define CONFIG_ADPCM_AGM_DECODER 0 #define CONFIG_ADPCM_AICA_DECODER 0 #define CONFIG_ADPCM_CT_DECODER 0 #define CONFIG_ADPCM_DTK_DECODER 0 @@ -1096,7 +1193,12 @@ #define CONFIG_PCM_MULAW_AT_DECODER 0 #define CONFIG_QDMC_AT_DECODER 0 #define CONFIG_QDM2_AT_DECODER 0 +#define CONFIG_LIBAOM_AV1_DECODER 0 +#define CONFIG_LIBARIBB24_DECODER 0 #define CONFIG_LIBCELT_DECODER 0 +#define CONFIG_LIBCODEC2_DECODER 0 +#define CONFIG_LIBDAV1D_DECODER 0 +#define CONFIG_LIBDAVS2_DECODER 0 #define CONFIG_LIBFDK_AAC_DECODER 0 #define CONFIG_LIBGSM_DECODER 0 #define CONFIG_LIBGSM_MS_DECODER 0 @@ -1105,7 +1207,7 @@ #define CONFIG_LIBOPENCORE_AMRWB_DECODER 0 #define CONFIG_LIBOPENJPEG_DECODER 0 #define CONFIG_LIBOPUS_DECODER 0 -#define CONFIG_LIBSCHROEDINGER_DECODER 0 +#define CONFIG_LIBRSVG_DECODER 0 #define CONFIG_LIBSPEEX_DECODER 0 #define CONFIG_LIBVORBIS_DECODER 0 #define CONFIG_LIBVPX_VP8_DECODER 0 @@ -1115,7 +1217,6 @@ #define CONFIG_XBIN_DECODER 0 #define CONFIG_IDF_DECODER 0 #define CONFIG_LIBOPENH264_DECODER 0 -#define CONFIG_H263_CUVID_DECODER 0 #define CONFIG_H264_CUVID_DECODER 0 #define CONFIG_HEVC_CUVID_DECODER 0 #define CONFIG_HEVC_MEDIACODEC_DECODER 0 @@ -1127,278 +1228,9 @@ #define CONFIG_VC1_CUVID_DECODER 0 #define CONFIG_VP8_CUVID_DECODER 0 #define CONFIG_VP8_MEDIACODEC_DECODER 0 +#define CONFIG_VP8_QSV_DECODER 0 #define CONFIG_VP9_CUVID_DECODER 0 #define CONFIG_VP9_MEDIACODEC_DECODER 0 -#define CONFIG_AA_DEMUXER 0 -#define CONFIG_AAC_DEMUXER 1 -#define CONFIG_AC3_DEMUXER 1 -#define CONFIG_ACM_DEMUXER 0 -#define CONFIG_ACT_DEMUXER 0 -#define CONFIG_ADF_DEMUXER 0 -#define CONFIG_ADP_DEMUXER 0 -#define CONFIG_ADS_DEMUXER 0 -#define CONFIG_ADX_DEMUXER 0 -#define CONFIG_AEA_DEMUXER 0 -#define CONFIG_AFC_DEMUXER 0 -#define CONFIG_AIFF_DEMUXER 0 -#define CONFIG_AIX_DEMUXER 0 -#define CONFIG_AMR_DEMUXER 1 -#define CONFIG_ANM_DEMUXER 0 -#define CONFIG_APC_DEMUXER 0 -#define CONFIG_APE_DEMUXER 1 -#define CONFIG_APNG_DEMUXER 0 -#define CONFIG_AQTITLE_DEMUXER 0 -#define CONFIG_ASF_DEMUXER 1 -#define CONFIG_ASF_O_DEMUXER 1 -#define CONFIG_ASS_DEMUXER 0 -#define CONFIG_AST_DEMUXER 0 -#define CONFIG_AU_DEMUXER 0 -#define CONFIG_AVI_DEMUXER 1 -#define CONFIG_AVISYNTH_DEMUXER 0 -#define CONFIG_AVR_DEMUXER 0 -#define CONFIG_AVS_DEMUXER 0 -#define CONFIG_BETHSOFTVID_DEMUXER 0 -#define CONFIG_BFI_DEMUXER 0 -#define CONFIG_BINTEXT_DEMUXER 0 -#define CONFIG_BINK_DEMUXER 0 -#define CONFIG_BIT_DEMUXER 0 -#define CONFIG_BMV_DEMUXER 0 -#define CONFIG_BFSTM_DEMUXER 0 -#define CONFIG_BRSTM_DEMUXER 0 -#define CONFIG_BOA_DEMUXER 0 -#define CONFIG_C93_DEMUXER 0 -#define CONFIG_CAF_DEMUXER 0 -#define CONFIG_CAVSVIDEO_DEMUXER 1 -#define CONFIG_CDG_DEMUXER 0 -#define CONFIG_CDXL_DEMUXER 0 -#define CONFIG_CINE_DEMUXER 0 -#define CONFIG_CONCAT_DEMUXER 1 -#define CONFIG_DATA_DEMUXER 0 -#define CONFIG_DAUD_DEMUXER 0 -#define CONFIG_DCSTR_DEMUXER 0 -#define CONFIG_DFA_DEMUXER 0 -#define CONFIG_DIRAC_DEMUXER 0 -#define CONFIG_DNXHD_DEMUXER 1 -#define CONFIG_DSF_DEMUXER 0 -#define CONFIG_DSICIN_DEMUXER 0 -#define CONFIG_DSS_DEMUXER 0 -#define CONFIG_DTS_DEMUXER 0 -#define CONFIG_DTSHD_DEMUXER 0 -#define CONFIG_DV_DEMUXER 0 -#define CONFIG_DVBSUB_DEMUXER 0 -#define CONFIG_DVBTXT_DEMUXER 0 -#define CONFIG_DXA_DEMUXER 0 -#define CONFIG_EA_DEMUXER 0 -#define CONFIG_EA_CDATA_DEMUXER 0 -#define CONFIG_EAC3_DEMUXER 1 -#define CONFIG_EPAF_DEMUXER 0 -#define CONFIG_FFM_DEMUXER 0 -#define CONFIG_FFMETADATA_DEMUXER 0 -#define CONFIG_FILMSTRIP_DEMUXER 0 -#define CONFIG_FLAC_DEMUXER 1 -#define CONFIG_FLIC_DEMUXER 0 -#define CONFIG_FLV_DEMUXER 1 -#define CONFIG_LIVE_FLV_DEMUXER 0 -#define CONFIG_FOURXM_DEMUXER 0 -#define CONFIG_FRM_DEMUXER 0 -#define CONFIG_FSB_DEMUXER 0 -#define CONFIG_G722_DEMUXER 0 -#define CONFIG_G723_1_DEMUXER 0 -#define CONFIG_G729_DEMUXER 0 -#define CONFIG_GENH_DEMUXER 0 -#define CONFIG_GIF_DEMUXER 1 -#define CONFIG_GSM_DEMUXER 0 -#define CONFIG_GXF_DEMUXER 0 -#define CONFIG_H261_DEMUXER 0 -#define CONFIG_H263_DEMUXER 1 -#define CONFIG_H264_DEMUXER 1 -#define CONFIG_HEVC_DEMUXER 1 -#define CONFIG_HLS_DEMUXER 1 -#define CONFIG_HNM_DEMUXER 0 -#define CONFIG_ICO_DEMUXER 0 -#define CONFIG_IDCIN_DEMUXER 0 -#define CONFIG_IDF_DEMUXER 0 -#define CONFIG_IFF_DEMUXER 0 -#define CONFIG_ILBC_DEMUXER 0 -#define CONFIG_IMAGE2_DEMUXER 1 -#define CONFIG_IMAGE2PIPE_DEMUXER 1 -#define CONFIG_IMAGE2_ALIAS_PIX_DEMUXER 0 -#define CONFIG_IMAGE2_BRENDER_PIX_DEMUXER 0 -#define CONFIG_INGENIENT_DEMUXER 0 -#define CONFIG_IPMOVIE_DEMUXER 0 -#define CONFIG_IRCAM_DEMUXER 0 -#define CONFIG_ISS_DEMUXER 0 -#define CONFIG_IV8_DEMUXER 0 -#define CONFIG_IVF_DEMUXER 0 -#define CONFIG_IVR_DEMUXER 0 -#define CONFIG_JACOSUB_DEMUXER 0 -#define CONFIG_JV_DEMUXER 0 -#define CONFIG_LMLM4_DEMUXER 0 -#define CONFIG_LOAS_DEMUXER 0 -#define CONFIG_LRC_DEMUXER 1 -#define CONFIG_LVF_DEMUXER 0 -#define CONFIG_LXF_DEMUXER 0 -#define CONFIG_M4V_DEMUXER 1 -#define CONFIG_MATROSKA_DEMUXER 1 -#define CONFIG_MGSTS_DEMUXER 0 -#define CONFIG_MICRODVD_DEMUXER 0 -#define CONFIG_MJPEG_DEMUXER 1 -#define CONFIG_MLP_DEMUXER 0 -#define CONFIG_MLV_DEMUXER 0 -#define CONFIG_MM_DEMUXER 0 -#define CONFIG_MMF_DEMUXER 0 -#define CONFIG_MOV_DEMUXER 1 -#define CONFIG_MP3_DEMUXER 1 -#define CONFIG_MPC_DEMUXER 0 -#define CONFIG_MPC8_DEMUXER 0 -#define CONFIG_MPEGPS_DEMUXER 0 -#define CONFIG_MPEGTS_DEMUXER 1 -#define CONFIG_MPEGTSRAW_DEMUXER 0 -#define CONFIG_MPEGVIDEO_DEMUXER 1 -#define CONFIG_MPJPEG_DEMUXER 0 -#define CONFIG_MPL2_DEMUXER 0 -#define CONFIG_MPSUB_DEMUXER 0 -#define CONFIG_MSF_DEMUXER 0 -#define CONFIG_MSNWC_TCP_DEMUXER 0 -#define CONFIG_MTAF_DEMUXER 0 -#define CONFIG_MTV_DEMUXER 0 -#define CONFIG_MUSX_DEMUXER 0 -#define CONFIG_MV_DEMUXER 1 -#define CONFIG_MVI_DEMUXER 0 -#define CONFIG_MXF_DEMUXER 0 -#define CONFIG_MXG_DEMUXER 0 -#define CONFIG_NC_DEMUXER 0 -#define CONFIG_NISTSPHERE_DEMUXER 0 -#define CONFIG_NSV_DEMUXER 0 -#define CONFIG_NUT_DEMUXER 0 -#define CONFIG_NUV_DEMUXER 0 -#define CONFIG_OGG_DEMUXER 1 -#define CONFIG_OMA_DEMUXER 0 -#define CONFIG_PAF_DEMUXER 0 -#define CONFIG_PCM_ALAW_DEMUXER 0 -#define CONFIG_PCM_MULAW_DEMUXER 0 -#define CONFIG_PCM_F64BE_DEMUXER 0 -#define CONFIG_PCM_F64LE_DEMUXER 0 -#define CONFIG_PCM_F32BE_DEMUXER 0 -#define CONFIG_PCM_F32LE_DEMUXER 0 -#define CONFIG_PCM_S32BE_DEMUXER 0 -#define CONFIG_PCM_S32LE_DEMUXER 0 -#define CONFIG_PCM_S24BE_DEMUXER 0 -#define CONFIG_PCM_S24LE_DEMUXER 0 -#define CONFIG_PCM_S16BE_DEMUXER 0 -#define CONFIG_PCM_S16LE_DEMUXER 0 -#define CONFIG_PCM_S8_DEMUXER 0 -#define CONFIG_PCM_U32BE_DEMUXER 0 -#define CONFIG_PCM_U32LE_DEMUXER 0 -#define CONFIG_PCM_U24BE_DEMUXER 0 -#define CONFIG_PCM_U24LE_DEMUXER 0 -#define CONFIG_PCM_U16BE_DEMUXER 0 -#define CONFIG_PCM_U16LE_DEMUXER 0 -#define CONFIG_PCM_U8_DEMUXER 0 -#define CONFIG_PJS_DEMUXER 0 -#define CONFIG_PMP_DEMUXER 0 -#define CONFIG_PVA_DEMUXER 0 -#define CONFIG_PVF_DEMUXER 0 -#define CONFIG_QCP_DEMUXER 0 -#define CONFIG_R3D_DEMUXER 0 -#define CONFIG_RAWVIDEO_DEMUXER 0 -#define CONFIG_REALTEXT_DEMUXER 1 -#define CONFIG_REDSPARK_DEMUXER 0 -#define CONFIG_RL2_DEMUXER 0 -#define CONFIG_RM_DEMUXER 1 -#define CONFIG_ROQ_DEMUXER 0 -#define CONFIG_RPL_DEMUXER 0 -#define CONFIG_RSD_DEMUXER 0 -#define CONFIG_RSO_DEMUXER 0 -#define CONFIG_RTP_DEMUXER 1 -#define CONFIG_RTSP_DEMUXER 1 -#define CONFIG_SAMI_DEMUXER 1 -#define CONFIG_SAP_DEMUXER 0 -#define CONFIG_SBG_DEMUXER 0 -#define CONFIG_SDP_DEMUXER 1 -#define CONFIG_SDR2_DEMUXER 0 -#define CONFIG_SEGAFILM_DEMUXER 0 -#define CONFIG_SHORTEN_DEMUXER 0 -#define CONFIG_SIFF_DEMUXER 0 -#define CONFIG_SLN_DEMUXER 0 -#define CONFIG_SMACKER_DEMUXER 0 -#define CONFIG_SMJPEG_DEMUXER 0 -#define CONFIG_SMUSH_DEMUXER 0 -#define CONFIG_SOL_DEMUXER 0 -#define CONFIG_SOX_DEMUXER 0 -#define CONFIG_SPDIF_DEMUXER 0 -#define CONFIG_SRT_DEMUXER 1 -#define CONFIG_STR_DEMUXER 0 -#define CONFIG_STL_DEMUXER 0 -#define CONFIG_SUBVIEWER1_DEMUXER 0 -#define CONFIG_SUBVIEWER_DEMUXER 0 -#define CONFIG_SUP_DEMUXER 0 -#define CONFIG_SVAG_DEMUXER 0 -#define CONFIG_SWF_DEMUXER 1 -#define CONFIG_TAK_DEMUXER 0 -#define CONFIG_TEDCAPTIONS_DEMUXER 0 -#define CONFIG_THP_DEMUXER 0 -#define CONFIG_THREEDOSTR_DEMUXER 0 -#define CONFIG_TIERTEXSEQ_DEMUXER 0 -#define CONFIG_TMV_DEMUXER 0 -#define CONFIG_TRUEHD_DEMUXER 0 -#define CONFIG_TTA_DEMUXER 0 -#define CONFIG_TXD_DEMUXER 0 -#define CONFIG_TTY_DEMUXER 0 -#define CONFIG_V210_DEMUXER 0 -#define CONFIG_V210X_DEMUXER 0 -#define CONFIG_VAG_DEMUXER 0 -#define CONFIG_VC1_DEMUXER 1 -#define CONFIG_VC1T_DEMUXER 0 -#define CONFIG_VIVO_DEMUXER 0 -#define CONFIG_VMD_DEMUXER 0 -#define CONFIG_VOBSUB_DEMUXER 0 -#define CONFIG_VOC_DEMUXER 0 -#define CONFIG_VPK_DEMUXER 0 -#define CONFIG_VPLAYER_DEMUXER 0 -#define CONFIG_VQF_DEMUXER 0 -#define CONFIG_W64_DEMUXER 0 -#define CONFIG_WAV_DEMUXER 1 -#define CONFIG_WC3_DEMUXER 0 -#define CONFIG_WEBM_DASH_MANIFEST_DEMUXER 0 -#define CONFIG_WEBVTT_DEMUXER 0 -#define CONFIG_WSAUD_DEMUXER 0 -#define CONFIG_WSD_DEMUXER 0 -#define CONFIG_WSVQA_DEMUXER 0 -#define CONFIG_WTV_DEMUXER 0 -#define CONFIG_WVE_DEMUXER 0 -#define CONFIG_WV_DEMUXER 0 -#define CONFIG_XA_DEMUXER 0 -#define CONFIG_XBIN_DEMUXER 0 -#define CONFIG_XMV_DEMUXER 1 -#define CONFIG_XVAG_DEMUXER 0 -#define CONFIG_XWMA_DEMUXER 0 -#define CONFIG_YOP_DEMUXER 0 -#define CONFIG_YUV4MPEGPIPE_DEMUXER 0 -#define CONFIG_IMAGE_BMP_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_DDS_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_DPX_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_EXR_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_J2K_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_JPEG_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PAM_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PBM_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PCX_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PGM_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PICTOR_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PNG_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_PPM_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_QDRAW_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_SGI_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_TIFF_PIPE_DEMUXER 0 -#define CONFIG_IMAGE_WEBP_PIPE_DEMUXER 0 -#define CONFIG_LIBGME_DEMUXER 0 -#define CONFIG_LIBMODPLUG_DEMUXER 0 -#define CONFIG_LIBNUT_DEMUXER 0 -#define CONFIG_LIBOPENMPT_DEMUXER 0 #define CONFIG_A64MULTI_ENCODER 1 #define CONFIG_A64MULTI5_ENCODER 1 #define CONFIG_ALIAS_PIX_ENCODER 1 @@ -1418,6 +1250,7 @@ #define CONFIG_DVVIDEO_ENCODER 1 #define CONFIG_FFV1_ENCODER 1 #define CONFIG_FFVHUFF_ENCODER 1 +#define CONFIG_FITS_ENCODER 1 #define CONFIG_FLASHSV_ENCODER 1 #define CONFIG_FLASHSV2_ENCODER 1 #define CONFIG_FLV_ENCODER 1 @@ -1430,6 +1263,7 @@ #define CONFIG_JPEG2000_ENCODER 1 #define CONFIG_JPEGLS_ENCODER 1 #define CONFIG_LJPEG_ENCODER 1 +#define CONFIG_MAGICYUV_ENCODER 1 #define CONFIG_MJPEG_ENCODER 1 #define CONFIG_MPEG1VIDEO_ENCODER 1 #define CONFIG_MPEG2VIDEO_ENCODER 1 @@ -1481,6 +1315,8 @@ #define CONFIG_AC3_ENCODER 1 #define CONFIG_AC3_FIXED_ENCODER 1 #define CONFIG_ALAC_ENCODER 1 +#define CONFIG_APTX_ENCODER 1 +#define CONFIG_APTX_HD_ENCODER 1 #define CONFIG_DCA_ENCODER 1 #define CONFIG_EAC3_ENCODER 1 #define CONFIG_FLAC_ENCODER 1 @@ -1489,7 +1325,9 @@ #define CONFIG_MP2_ENCODER 1 #define CONFIG_MP2FIXED_ENCODER 1 #define CONFIG_NELLYMOSER_ENCODER 1 +#define CONFIG_OPUS_ENCODER 1 #define CONFIG_RA_144_ENCODER 1 +#define CONFIG_SBC_ENCODER 1 #define CONFIG_SONIC_ENCODER 1 #define CONFIG_SONIC_LS_ENCODER 1 #define CONFIG_TRUEHD_ENCODER 1 @@ -1499,6 +1337,7 @@ #define CONFIG_WMAV1_ENCODER 1 #define CONFIG_WMAV2_ENCODER 1 #define CONFIG_PCM_ALAW_ENCODER 1 +#define CONFIG_PCM_DVD_ENCODER 1 #define CONFIG_PCM_F32BE_ENCODER 1 #define CONFIG_PCM_F32LE_ENCODER 1 #define CONFIG_PCM_F64BE_ENCODER 1 @@ -1526,10 +1365,12 @@ #define CONFIG_PCM_U24LE_ENCODER 1 #define CONFIG_PCM_U32BE_ENCODER 1 #define CONFIG_PCM_U32LE_ENCODER 1 +#define CONFIG_PCM_VIDC_ENCODER 1 #define CONFIG_ROQ_DPCM_ENCODER 1 #define CONFIG_ADPCM_ADX_ENCODER 1 #define CONFIG_ADPCM_G722_ENCODER 1 #define CONFIG_ADPCM_G726_ENCODER 1 +#define CONFIG_ADPCM_G726LE_ENCODER 1 #define CONFIG_ADPCM_IMA_QT_ENCODER 1 #define CONFIG_ADPCM_IMA_WAV_ENCODER 1 #define CONFIG_ADPCM_MS_ENCODER 1 @@ -1550,6 +1391,8 @@ #define CONFIG_ILBC_AT_ENCODER 0 #define CONFIG_PCM_ALAW_AT_ENCODER 0 #define CONFIG_PCM_MULAW_AT_ENCODER 0 +#define CONFIG_LIBAOM_AV1_ENCODER 0 +#define CONFIG_LIBCODEC2_ENCODER 0 #define CONFIG_LIBFDK_AAC_ENCODER 0 #define CONFIG_LIBGSM_ENCODER 0 #define CONFIG_LIBGSM_MS_ENCODER 0 @@ -1558,7 +1401,6 @@ #define CONFIG_LIBOPENCORE_AMRNB_ENCODER 0 #define CONFIG_LIBOPENJPEG_ENCODER 0 #define CONFIG_LIBOPUS_ENCODER 0 -#define CONFIG_LIBSCHROEDINGER_ENCODER 0 #define CONFIG_LIBSHINE_ENCODER 0 #define CONFIG_LIBSPEEX_ENCODER 0 #define CONFIG_LIBTHEORA_ENCODER 0 @@ -1575,34 +1417,188 @@ #define CONFIG_LIBX264RGB_ENCODER 1 #define CONFIG_LIBX265_ENCODER 0 #define CONFIG_LIBXAVS_ENCODER 0 +#define CONFIG_LIBXAVS2_ENCODER 0 #define CONFIG_LIBXVID_ENCODER 0 +#define CONFIG_H263_V4L2M2M_ENCODER 0 #define CONFIG_LIBOPENH264_ENCODER 0 +#define CONFIG_H264_AMF_ENCODER 0 #define CONFIG_H264_NVENC_ENCODER 0 #define CONFIG_H264_OMX_ENCODER 0 #define CONFIG_H264_QSV_ENCODER 0 +#define CONFIG_H264_V4L2M2M_ENCODER 0 #define CONFIG_H264_VAAPI_ENCODER 0 #define CONFIG_H264_VIDEOTOOLBOX_ENCODER 0 #define CONFIG_NVENC_ENCODER 0 #define CONFIG_NVENC_H264_ENCODER 0 #define CONFIG_NVENC_HEVC_ENCODER 0 +#define CONFIG_HEVC_AMF_ENCODER 0 #define CONFIG_HEVC_NVENC_ENCODER 0 #define CONFIG_HEVC_QSV_ENCODER 0 +#define CONFIG_HEVC_V4L2M2M_ENCODER 0 #define CONFIG_HEVC_VAAPI_ENCODER 0 +#define CONFIG_HEVC_VIDEOTOOLBOX_ENCODER 0 #define CONFIG_LIBKVAZAAR_ENCODER 0 +#define CONFIG_MJPEG_QSV_ENCODER 0 #define CONFIG_MJPEG_VAAPI_ENCODER 0 #define CONFIG_MPEG2_QSV_ENCODER 0 +#define CONFIG_MPEG2_VAAPI_ENCODER 0 +#define CONFIG_MPEG4_V4L2M2M_ENCODER 0 +#define CONFIG_VP8_V4L2M2M_ENCODER 0 +#define CONFIG_VP8_VAAPI_ENCODER 0 +#define CONFIG_VP9_VAAPI_ENCODER 0 +#define CONFIG_H263_VAAPI_HWACCEL 0 +#define CONFIG_H263_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_H264_D3D11VA_HWACCEL 0 +#define CONFIG_H264_D3D11VA2_HWACCEL 0 +#define CONFIG_H264_DXVA2_HWACCEL 0 +#define CONFIG_H264_NVDEC_HWACCEL 0 +#define CONFIG_H264_VAAPI_HWACCEL 0 +#define CONFIG_H264_VDPAU_HWACCEL 0 +#define CONFIG_H264_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_HEVC_D3D11VA_HWACCEL 0 +#define CONFIG_HEVC_D3D11VA2_HWACCEL 0 +#define CONFIG_HEVC_DXVA2_HWACCEL 0 +#define CONFIG_HEVC_NVDEC_HWACCEL 0 +#define CONFIG_HEVC_VAAPI_HWACCEL 0 +#define CONFIG_HEVC_VDPAU_HWACCEL 0 +#define CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_MJPEG_NVDEC_HWACCEL 0 +#define CONFIG_MJPEG_VAAPI_HWACCEL 0 +#define CONFIG_MPEG1_NVDEC_HWACCEL 0 +#define CONFIG_MPEG1_VDPAU_HWACCEL 0 +#define CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_MPEG1_XVMC_HWACCEL 0 +#define CONFIG_MPEG2_D3D11VA_HWACCEL 0 +#define CONFIG_MPEG2_D3D11VA2_HWACCEL 0 +#define CONFIG_MPEG2_NVDEC_HWACCEL 0 +#define CONFIG_MPEG2_DXVA2_HWACCEL 0 +#define CONFIG_MPEG2_VAAPI_HWACCEL 0 +#define CONFIG_MPEG2_VDPAU_HWACCEL 0 +#define CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_MPEG2_XVMC_HWACCEL 0 +#define CONFIG_MPEG4_NVDEC_HWACCEL 0 +#define CONFIG_MPEG4_VAAPI_HWACCEL 0 +#define CONFIG_MPEG4_VDPAU_HWACCEL 0 +#define CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL 0 +#define CONFIG_VC1_D3D11VA_HWACCEL 0 +#define CONFIG_VC1_D3D11VA2_HWACCEL 0 +#define CONFIG_VC1_DXVA2_HWACCEL 0 +#define CONFIG_VC1_NVDEC_HWACCEL 0 +#define CONFIG_VC1_VAAPI_HWACCEL 0 +#define CONFIG_VC1_VDPAU_HWACCEL 0 +#define CONFIG_VP8_NVDEC_HWACCEL 0 +#define CONFIG_VP8_VAAPI_HWACCEL 0 +#define CONFIG_VP9_D3D11VA_HWACCEL 0 +#define CONFIG_VP9_D3D11VA2_HWACCEL 0 +#define CONFIG_VP9_DXVA2_HWACCEL 0 +#define CONFIG_VP9_NVDEC_HWACCEL 0 +#define CONFIG_VP9_VAAPI_HWACCEL 0 +#define CONFIG_WMV3_D3D11VA_HWACCEL 0 +#define CONFIG_WMV3_D3D11VA2_HWACCEL 0 +#define CONFIG_WMV3_DXVA2_HWACCEL 0 +#define CONFIG_WMV3_NVDEC_HWACCEL 0 +#define CONFIG_WMV3_VAAPI_HWACCEL 0 +#define CONFIG_WMV3_VDPAU_HWACCEL 0 +#define CONFIG_AAC_PARSER 1 +#define CONFIG_AAC_LATM_PARSER 1 +#define CONFIG_AC3_PARSER 1 +#define CONFIG_ADX_PARSER 1 +#define CONFIG_AV1_PARSER 1 +#define CONFIG_AVS2_PARSER 1 +#define CONFIG_BMP_PARSER 1 +#define CONFIG_CAVSVIDEO_PARSER 1 +#define CONFIG_COOK_PARSER 1 +#define CONFIG_DCA_PARSER 1 +#define CONFIG_DIRAC_PARSER 1 +#define CONFIG_DNXHD_PARSER 1 +#define CONFIG_DPX_PARSER 1 +#define CONFIG_DVAUDIO_PARSER 1 +#define CONFIG_DVBSUB_PARSER 1 +#define CONFIG_DVDSUB_PARSER 1 +#define CONFIG_DVD_NAV_PARSER 1 +#define CONFIG_FLAC_PARSER 1 +#define CONFIG_G723_1_PARSER 1 +#define CONFIG_G729_PARSER 1 +#define CONFIG_GIF_PARSER 1 +#define CONFIG_GSM_PARSER 1 +#define CONFIG_H261_PARSER 1 +#define CONFIG_H263_PARSER 1 +#define CONFIG_H264_PARSER 1 +#define CONFIG_HEVC_PARSER 1 +#define CONFIG_MJPEG_PARSER 1 +#define CONFIG_MLP_PARSER 1 +#define CONFIG_MPEG4VIDEO_PARSER 1 +#define CONFIG_MPEGAUDIO_PARSER 1 +#define CONFIG_MPEGVIDEO_PARSER 1 +#define CONFIG_OPUS_PARSER 1 +#define CONFIG_PNG_PARSER 1 +#define CONFIG_PNM_PARSER 1 +#define CONFIG_RV30_PARSER 1 +#define CONFIG_RV40_PARSER 1 +#define CONFIG_SBC_PARSER 1 +#define CONFIG_SIPR_PARSER 1 +#define CONFIG_TAK_PARSER 1 +#define CONFIG_VC1_PARSER 1 +#define CONFIG_VORBIS_PARSER 1 +#define CONFIG_VP3_PARSER 1 +#define CONFIG_VP8_PARSER 1 +#define CONFIG_VP9_PARSER 1 +#define CONFIG_XMA_PARSER 1 +#define CONFIG_ALSA_INDEV 0 +#define CONFIG_ANDROID_CAMERA_INDEV 0 +#define CONFIG_AVFOUNDATION_INDEV 0 +#define CONFIG_BKTR_INDEV 0 +#define CONFIG_DECKLINK_INDEV 0 +#define CONFIG_DSHOW_INDEV 0 +#define CONFIG_FBDEV_INDEV 0 +#define CONFIG_GDIGRAB_INDEV 0 +#define CONFIG_IEC61883_INDEV 0 +#define CONFIG_JACK_INDEV 0 +#define CONFIG_KMSGRAB_INDEV 0 +#define CONFIG_LAVFI_INDEV 0 +#define CONFIG_OPENAL_INDEV 0 +#define CONFIG_OSS_INDEV 0 +#define CONFIG_PULSE_INDEV 0 +#define CONFIG_SNDIO_INDEV 0 +#define CONFIG_V4L2_INDEV 0 +#define CONFIG_VFWCAP_INDEV 0 +#define CONFIG_XCBGRAB_INDEV 0 +#define CONFIG_LIBCDIO_INDEV 0 +#define CONFIG_LIBDC1394_INDEV 0 +#define CONFIG_ALSA_OUTDEV 0 +#define CONFIG_CACA_OUTDEV 0 +#define CONFIG_DECKLINK_OUTDEV 0 +#define CONFIG_FBDEV_OUTDEV 0 +#define CONFIG_OPENGL_OUTDEV 0 +#define CONFIG_OSS_OUTDEV 0 +#define CONFIG_PULSE_OUTDEV 0 +#define CONFIG_SDL2_OUTDEV 0 +#define CONFIG_SNDIO_OUTDEV 0 +#define CONFIG_V4L2_OUTDEV 0 +#define CONFIG_XV_OUTDEV 0 #define CONFIG_ABENCH_FILTER 1 #define CONFIG_ACOMPRESSOR_FILTER 1 +#define CONFIG_ACONTRAST_FILTER 1 +#define CONFIG_ACOPY_FILTER 1 +#define CONFIG_ACUE_FILTER 1 #define CONFIG_ACROSSFADE_FILTER 1 +#define CONFIG_ACROSSOVER_FILTER 1 #define CONFIG_ACRUSHER_FILTER 1 +#define CONFIG_ADECLICK_FILTER 1 +#define CONFIG_ADECLIP_FILTER 1 #define CONFIG_ADELAY_FILTER 1 +#define CONFIG_ADERIVATIVE_FILTER 1 #define CONFIG_AECHO_FILTER 1 #define CONFIG_AEMPHASIS_FILTER 1 #define CONFIG_AEVAL_FILTER 1 #define CONFIG_AFADE_FILTER 1 +#define CONFIG_AFFTDN_FILTER 1 #define CONFIG_AFFTFILT_FILTER 1 +#define CONFIG_AFIR_FILTER 1 #define CONFIG_AFORMAT_FILTER 1 #define CONFIG_AGATE_FILTER 1 +#define CONFIG_AIIR_FILTER 1 +#define CONFIG_AINTEGRAL_FILTER 1 #define CONFIG_AINTERLEAVE_FILTER 1 #define CONFIG_ALIMITER_FILTER 1 #define CONFIG_ALLPASS_FILTER 1 @@ -1610,7 +1606,9 @@ #define CONFIG_AMERGE_FILTER 1 #define CONFIG_AMETADATA_FILTER 1 #define CONFIG_AMIX_FILTER 1 +#define CONFIG_AMULTIPLY_FILTER 1 #define CONFIG_ANEQUALIZER_FILTER 1 +#define CONFIG_ANLMDN_FILTER 1 #define CONFIG_ANULL_FILTER 1 #define CONFIG_APAD_FILTER 1 #define CONFIG_APERMS_FILTER 1 @@ -1627,10 +1625,11 @@ #define CONFIG_ASETTB_FILTER 1 #define CONFIG_ASHOWINFO_FILTER 1 #define CONFIG_ASIDEDATA_FILTER 1 +#define CONFIG_ASOFTCLIP_FILTER 1 #define CONFIG_ASPLIT_FILTER 1 +#define CONFIG_ASR_FILTER 0 #define CONFIG_ASTATS_FILTER 1 #define CONFIG_ASTREAMSELECT_FILTER 1 -#define CONFIG_ASYNCTS_FILTER 0 #define CONFIG_ATEMPO_FILTER 1 #define CONFIG_ATRIM_FILTER 1 #define CONFIG_AZMQ_FILTER 0 @@ -1644,8 +1643,11 @@ #define CONFIG_CHORUS_FILTER 1 #define CONFIG_COMPAND_FILTER 1 #define CONFIG_COMPENSATIONDELAY_FILTER 1 +#define CONFIG_CROSSFEED_FILTER 1 #define CONFIG_CRYSTALIZER_FILTER 1 #define CONFIG_DCSHIFT_FILTER 1 +#define CONFIG_DEESSER_FILTER 1 +#define CONFIG_DRMETER_FILTER 1 #define CONFIG_DYNAUDNORM_FILTER 1 #define CONFIG_EARWAX_FILTER 1 #define CONFIG_EBUR128_FILTER 1 @@ -1653,12 +1655,18 @@ #define CONFIG_EXTRASTEREO_FILTER 1 #define CONFIG_FIREQUALIZER_FILTER 1 #define CONFIG_FLANGER_FILTER 1 +#define CONFIG_HAAS_FILTER 1 #define CONFIG_HDCD_FILTER 1 +#define CONFIG_HEADPHONE_FILTER 1 #define CONFIG_HIGHPASS_FILTER 1 +#define CONFIG_HIGHSHELF_FILTER 1 #define CONFIG_JOIN_FILTER 1 #define CONFIG_LADSPA_FILTER 0 -#define CONFIG_LOUDNORM_FILTER 0 +#define CONFIG_LOUDNORM_FILTER 1 #define CONFIG_LOWPASS_FILTER 1 +#define CONFIG_LOWSHELF_FILTER 1 +#define CONFIG_LV2_FILTER 0 +#define CONFIG_MCOMPAND_FILTER 1 #define CONFIG_PAN_FILTER 1 #define CONFIG_REPLAYGAIN_FILTER 1 #define CONFIG_RESAMPLE_FILTER 0 @@ -1670,6 +1678,8 @@ #define CONFIG_SOFALIZER_FILTER 0 #define CONFIG_STEREOTOOLS_FILTER 1 #define CONFIG_STEREOWIDEN_FILTER 1 +#define CONFIG_SUPEREQUALIZER_FILTER 1 +#define CONFIG_SURROUND_FILTER 1 #define CONFIG_TREBLE_FILTER 1 #define CONFIG_TREMOLO_FILTER 1 #define CONFIG_VIBRATO_FILTER 1 @@ -1679,74 +1689,106 @@ #define CONFIG_ANOISESRC_FILTER 1 #define CONFIG_ANULLSRC_FILTER 1 #define CONFIG_FLITE_FILTER 0 +#define CONFIG_HILBERT_FILTER 1 +#define CONFIG_SINC_FILTER 1 #define CONFIG_SINE_FILTER 1 #define CONFIG_ANULLSINK_FILTER 1 #define CONFIG_ALPHAEXTRACT_FILTER 1 #define CONFIG_ALPHAMERGE_FILTER 1 +#define CONFIG_AMPLIFY_FILTER 1 #define CONFIG_ASS_FILTER 0 #define CONFIG_ATADENOISE_FILTER 1 #define CONFIG_AVGBLUR_FILTER 1 +#define CONFIG_AVGBLUR_OPENCL_FILTER 0 #define CONFIG_BBOX_FILTER 1 #define CONFIG_BENCH_FILTER 1 #define CONFIG_BITPLANENOISE_FILTER 1 #define CONFIG_BLACKDETECT_FILTER 1 #define CONFIG_BLACKFRAME_FILTER 1 #define CONFIG_BLEND_FILTER 1 +#define CONFIG_BM3D_FILTER 1 #define CONFIG_BOXBLUR_FILTER 1 +#define CONFIG_BOXBLUR_OPENCL_FILTER 0 #define CONFIG_BWDIF_FILTER 1 +#define CONFIG_CHROMAHOLD_FILTER 1 #define CONFIG_CHROMAKEY_FILTER 1 +#define CONFIG_CHROMASHIFT_FILTER 1 #define CONFIG_CIESCOPE_FILTER 1 #define CONFIG_CODECVIEW_FILTER 1 #define CONFIG_COLORBALANCE_FILTER 1 #define CONFIG_COLORCHANNELMIXER_FILTER 1 #define CONFIG_COLORKEY_FILTER 1 +#define CONFIG_COLORKEY_OPENCL_FILTER 0 +#define CONFIG_COLORHOLD_FILTER 1 #define CONFIG_COLORLEVELS_FILTER 1 #define CONFIG_COLORMATRIX_FILTER 1 #define CONFIG_COLORSPACE_FILTER 1 #define CONFIG_CONVOLUTION_FILTER 1 +#define CONFIG_CONVOLUTION_OPENCL_FILTER 0 +#define CONFIG_CONVOLVE_FILTER 1 #define CONFIG_COPY_FILTER 1 #define CONFIG_COREIMAGE_FILTER 0 #define CONFIG_COVER_RECT_FILTER 1 #define CONFIG_CROP_FILTER 1 #define CONFIG_CROPDETECT_FILTER 1 +#define CONFIG_CUE_FILTER 1 #define CONFIG_CURVES_FILTER 1 #define CONFIG_DATASCOPE_FILTER 1 #define CONFIG_DCTDNOIZ_FILTER 1 #define CONFIG_DEBAND_FILTER 1 +#define CONFIG_DEBLOCK_FILTER 1 #define CONFIG_DECIMATE_FILTER 1 +#define CONFIG_DECONVOLVE_FILTER 1 +#define CONFIG_DEDOT_FILTER 1 #define CONFIG_DEFLATE_FILTER 1 +#define CONFIG_DEFLICKER_FILTER 1 +#define CONFIG_DEINTERLACE_QSV_FILTER 0 +#define CONFIG_DEINTERLACE_VAAPI_FILTER 0 #define CONFIG_DEJUDDER_FILTER 1 #define CONFIG_DELOGO_FILTER 1 +#define CONFIG_DENOISE_VAAPI_FILTER 0 +#define CONFIG_DERAIN_FILTER 1 #define CONFIG_DESHAKE_FILTER 1 +#define CONFIG_DESPILL_FILTER 1 #define CONFIG_DETELECINE_FILTER 1 #define CONFIG_DILATION_FILTER 1 +#define CONFIG_DILATION_OPENCL_FILTER 0 #define CONFIG_DISPLACE_FILTER 1 +#define CONFIG_DOUBLEWEAVE_FILTER 1 #define CONFIG_DRAWBOX_FILTER 1 #define CONFIG_DRAWGRAPH_FILTER 1 #define CONFIG_DRAWGRID_FILTER 1 #define CONFIG_DRAWTEXT_FILTER 0 #define CONFIG_EDGEDETECT_FILTER 1 #define CONFIG_ELBG_FILTER 1 +#define CONFIG_ENTROPY_FILTER 1 #define CONFIG_EQ_FILTER 1 #define CONFIG_EROSION_FILTER 1 +#define CONFIG_EROSION_OPENCL_FILTER 0 #define CONFIG_EXTRACTPLANES_FILTER 1 #define CONFIG_FADE_FILTER 1 +#define CONFIG_FFTDNOIZ_FILTER 1 #define CONFIG_FFTFILT_FILTER 1 #define CONFIG_FIELD_FILTER 1 #define CONFIG_FIELDHINT_FILTER 1 #define CONFIG_FIELDMATCH_FILTER 1 #define CONFIG_FIELDORDER_FILTER 1 +#define CONFIG_FILLBORDERS_FILTER 1 #define CONFIG_FIND_RECT_FILTER 1 +#define CONFIG_FLOODFILL_FILTER 1 #define CONFIG_FORMAT_FILTER 1 #define CONFIG_FPS_FILTER 1 #define CONFIG_FRAMEPACK_FILTER 1 #define CONFIG_FRAMERATE_FILTER 1 #define CONFIG_FRAMESTEP_FILTER 1 +#define CONFIG_FREEZEDETECT_FILTER 1 #define CONFIG_FREI0R_FILTER 0 #define CONFIG_FSPP_FILTER 1 #define CONFIG_GBLUR_FILTER 1 #define CONFIG_GEQ_FILTER 1 #define CONFIG_GRADFUN_FILTER 1 +#define CONFIG_GRAPHMONITOR_FILTER 1 +#define CONFIG_GREYEDGE_FILTER 1 #define CONFIG_HALDCLUT_FILTER 1 #define CONFIG_HFLIP_FILTER 1 #define CONFIG_HISTEQ_FILTER 1 @@ -1756,6 +1798,7 @@ #define CONFIG_HSTACK_FILTER 1 #define CONFIG_HUE_FILTER 1 #define CONFIG_HWDOWNLOAD_FILTER 1 +#define CONFIG_HWMAP_FILTER 1 #define CONFIG_HWUPLOAD_FILTER 1 #define CONFIG_HWUPLOAD_CUDA_FILTER 0 #define CONFIG_HYSTERESIS_FILTER 1 @@ -1765,30 +1808,44 @@ #define CONFIG_INTERLACE_FILTER 1 #define CONFIG_INTERLEAVE_FILTER 1 #define CONFIG_KERNDEINT_FILTER 1 +#define CONFIG_LAGFUN_FILTER 1 #define CONFIG_LENSCORRECTION_FILTER 1 +#define CONFIG_LENSFUN_FILTER 0 +#define CONFIG_LIBVMAF_FILTER 0 +#define CONFIG_LIMITER_FILTER 1 #define CONFIG_LOOP_FILTER 1 +#define CONFIG_LUMAKEY_FILTER 1 #define CONFIG_LUT_FILTER 1 +#define CONFIG_LUT1D_FILTER 1 #define CONFIG_LUT2_FILTER 1 #define CONFIG_LUT3D_FILTER 1 #define CONFIG_LUTRGB_FILTER 1 #define CONFIG_LUTYUV_FILTER 1 #define CONFIG_MASKEDCLAMP_FILTER 1 #define CONFIG_MASKEDMERGE_FILTER 1 +#define CONFIG_MASKFUN_FILTER 1 #define CONFIG_MCDEINT_FILTER 1 #define CONFIG_MERGEPLANES_FILTER 1 #define CONFIG_MESTIMATE_FILTER 1 #define CONFIG_METADATA_FILTER 1 +#define CONFIG_MIDEQUALIZER_FILTER 1 #define CONFIG_MINTERPOLATE_FILTER 1 +#define CONFIG_MIX_FILTER 1 #define CONFIG_MPDECIMATE_FILTER 1 #define CONFIG_NEGATE_FILTER 1 #define CONFIG_NLMEANS_FILTER 1 +#define CONFIG_NLMEANS_OPENCL_FILTER 0 #define CONFIG_NNEDI_FILTER 1 #define CONFIG_NOFORMAT_FILTER 1 #define CONFIG_NOISE_FILTER 1 +#define CONFIG_NORMALIZE_FILTER 1 #define CONFIG_NULL_FILTER 1 #define CONFIG_OCR_FILTER 0 #define CONFIG_OCV_FILTER 0 +#define CONFIG_OSCILLOSCOPE_FILTER 1 #define CONFIG_OVERLAY_FILTER 1 +#define CONFIG_OVERLAY_OPENCL_FILTER 0 +#define CONFIG_OVERLAY_QSV_FILTER 0 #define CONFIG_OWDENOISE_FILTER 1 #define CONFIG_PAD_FILTER 1 #define CONFIG_PALETTEGEN_FILTER 1 @@ -1797,13 +1854,20 @@ #define CONFIG_PERSPECTIVE_FILTER 1 #define CONFIG_PHASE_FILTER 1 #define CONFIG_PIXDESCTEST_FILTER 1 +#define CONFIG_PIXSCOPE_FILTER 1 #define CONFIG_PP_FILTER 1 #define CONFIG_PP7_FILTER 1 +#define CONFIG_PREMULTIPLY_FILTER 1 #define CONFIG_PREWITT_FILTER 1 +#define CONFIG_PREWITT_OPENCL_FILTER 0 +#define CONFIG_PROCAMP_VAAPI_FILTER 0 +#define CONFIG_PROGRAM_OPENCL_FILTER 0 +#define CONFIG_PSEUDOCOLOR_FILTER 1 #define CONFIG_PSNR_FILTER 1 #define CONFIG_PULLUP_FILTER 1 #define CONFIG_QP_FILTER 1 #define CONFIG_RANDOM_FILTER 1 +#define CONFIG_READEIA608_FILTER 1 #define CONFIG_READVITC_FILTER 1 #define CONFIG_REALTIME_FILTER 1 #define CONFIG_REMAP_FILTER 1 @@ -1811,10 +1875,15 @@ #define CONFIG_REMOVELOGO_FILTER 1 #define CONFIG_REPEATFIELDS_FILTER 1 #define CONFIG_REVERSE_FILTER 1 +#define CONFIG_RGBASHIFT_FILTER 1 +#define CONFIG_ROBERTS_FILTER 1 +#define CONFIG_ROBERTS_OPENCL_FILTER 0 #define CONFIG_ROTATE_FILTER 1 #define CONFIG_SAB_FILTER 1 #define CONFIG_SCALE_FILTER 1 +#define CONFIG_SCALE_CUDA_FILTER 0 #define CONFIG_SCALE_NPP_FILTER 0 +#define CONFIG_SCALE_QSV_FILTER 0 #define CONFIG_SCALE_VAAPI_FILTER 0 #define CONFIG_SCALE2REF_FILTER 1 #define CONFIG_SELECT_FILTER 1 @@ -1823,19 +1892,25 @@ #define CONFIG_SEPARATEFIELDS_FILTER 1 #define CONFIG_SETDAR_FILTER 1 #define CONFIG_SETFIELD_FILTER 1 +#define CONFIG_SETPARAMS_FILTER 1 #define CONFIG_SETPTS_FILTER 1 +#define CONFIG_SETRANGE_FILTER 1 #define CONFIG_SETSAR_FILTER 1 #define CONFIG_SETTB_FILTER 1 +#define CONFIG_SHARPNESS_VAAPI_FILTER 0 #define CONFIG_SHOWINFO_FILTER 1 #define CONFIG_SHOWPALETTE_FILTER 1 #define CONFIG_SHUFFLEFRAMES_FILTER 1 #define CONFIG_SHUFFLEPLANES_FILTER 1 #define CONFIG_SIDEDATA_FILTER 1 #define CONFIG_SIGNALSTATS_FILTER 1 +#define CONFIG_SIGNATURE_FILTER 1 #define CONFIG_SMARTBLUR_FILTER 1 #define CONFIG_SOBEL_FILTER 1 +#define CONFIG_SOBEL_OPENCL_FILTER 0 #define CONFIG_SPLIT_FILTER 1 #define CONFIG_SPP_FILTER 1 +#define CONFIG_SR_FILTER 1 #define CONFIG_SSIM_FILTER 1 #define CONFIG_STEREO3D_FILTER 1 #define CONFIG_STREAMSELECT_FILTER 1 @@ -1845,25 +1920,44 @@ #define CONFIG_SWAPUV_FILTER 1 #define CONFIG_TBLEND_FILTER 1 #define CONFIG_TELECINE_FILTER 1 +#define CONFIG_THRESHOLD_FILTER 1 #define CONFIG_THUMBNAIL_FILTER 1 +#define CONFIG_THUMBNAIL_CUDA_FILTER 0 #define CONFIG_TILE_FILTER 1 #define CONFIG_TINTERLACE_FILTER 1 +#define CONFIG_TLUT2_FILTER 1 +#define CONFIG_TMIX_FILTER 1 +#define CONFIG_TONEMAP_FILTER 1 +#define CONFIG_TONEMAP_OPENCL_FILTER 0 +#define CONFIG_TPAD_FILTER 1 #define CONFIG_TRANSPOSE_FILTER 1 +#define CONFIG_TRANSPOSE_NPP_FILTER 0 +#define CONFIG_TRANSPOSE_OPENCL_FILTER 0 +#define CONFIG_TRANSPOSE_VAAPI_FILTER 0 #define CONFIG_TRIM_FILTER 1 +#define CONFIG_UNPREMULTIPLY_FILTER 1 #define CONFIG_UNSHARP_FILTER 1 +#define CONFIG_UNSHARP_OPENCL_FILTER 0 #define CONFIG_USPP_FILTER 1 #define CONFIG_VAGUEDENOISER_FILTER 1 #define CONFIG_VECTORSCOPE_FILTER 1 #define CONFIG_VFLIP_FILTER 1 +#define CONFIG_VFRDET_FILTER 1 +#define CONFIG_VIBRANCE_FILTER 1 #define CONFIG_VIDSTABDETECT_FILTER 0 #define CONFIG_VIDSTABTRANSFORM_FILTER 0 #define CONFIG_VIGNETTE_FILTER 1 +#define CONFIG_VMAFMOTION_FILTER 1 +#define CONFIG_VPP_QSV_FILTER 0 #define CONFIG_VSTACK_FILTER 1 #define CONFIG_W3FDIF_FILTER 1 #define CONFIG_WAVEFORM_FILTER 1 #define CONFIG_WEAVE_FILTER 1 #define CONFIG_XBR_FILTER 1 +#define CONFIG_XMEDIAN_FILTER 1 +#define CONFIG_XSTACK_FILTER 1 #define CONFIG_YADIF_FILTER 1 +#define CONFIG_YADIF_CUDA_FILTER 0 #define CONFIG_ZMQ_FILTER 0 #define CONFIG_ZOOMPAN_FILTER 1 #define CONFIG_ZSCALE_FILTER 0 @@ -1878,6 +1972,9 @@ #define CONFIG_MANDELBROT_FILTER 1 #define CONFIG_MPTESTSRC_FILTER 1 #define CONFIG_NULLSRC_FILTER 1 +#define CONFIG_OPENCLSRC_FILTER 0 +#define CONFIG_PAL75BARS_FILTER 1 +#define CONFIG_PAL100BARS_FILTER 1 #define CONFIG_RGBTESTSRC_FILTER 1 #define CONFIG_SMPTEBARS_FILTER 1 #define CONFIG_SMPTEHDBARS_FILTER 1 @@ -1885,13 +1982,16 @@ #define CONFIG_TESTSRC2_FILTER 1 #define CONFIG_YUVTESTSRC_FILTER 1 #define CONFIG_NULLSINK_FILTER 1 +#define CONFIG_ABITSCOPE_FILTER 1 #define CONFIG_ADRAWGRAPH_FILTER 1 +#define CONFIG_AGRAPHMONITOR_FILTER 1 #define CONFIG_AHISTOGRAM_FILTER 1 #define CONFIG_APHASEMETER_FILTER 1 #define CONFIG_AVECTORSCOPE_FILTER 1 #define CONFIG_CONCAT_FILTER 1 #define CONFIG_SHOWCQT_FILTER 1 #define CONFIG_SHOWFREQS_FILTER 1 +#define CONFIG_SHOWSPATIAL_FILTER 1 #define CONFIG_SHOWSPECTRUM_FILTER 1 #define CONFIG_SHOWSPECTRUMPIC_FILTER 1 #define CONFIG_SHOWVOLUME_FILTER 1 @@ -1900,87 +2000,309 @@ #define CONFIG_SPECTRUMSYNTH_FILTER 1 #define CONFIG_AMOVIE_FILTER 1 #define CONFIG_MOVIE_FILTER 1 -#define CONFIG_H263_CUVID_HWACCEL 0 -#define CONFIG_H263_VAAPI_HWACCEL 0 -#define CONFIG_H263_VIDEOTOOLBOX_HWACCEL 0 -#define CONFIG_H264_CUVID_HWACCEL 0 -#define CONFIG_H264_D3D11VA_HWACCEL 0 -#define CONFIG_H264_DXVA2_HWACCEL 0 -#define CONFIG_H264_MEDIACODEC_HWACCEL 0 -#define CONFIG_H264_MMAL_HWACCEL 0 -#define CONFIG_H264_QSV_HWACCEL 0 -#define CONFIG_H264_VAAPI_HWACCEL 0 -#define CONFIG_H264_VDA_HWACCEL 0 -#define CONFIG_H264_VDA_OLD_HWACCEL 0 -#define CONFIG_H264_VDPAU_HWACCEL 0 -#define CONFIG_H264_VIDEOTOOLBOX_HWACCEL 0 -#define CONFIG_HEVC_CUVID_HWACCEL 0 -#define CONFIG_HEVC_D3D11VA_HWACCEL 0 -#define CONFIG_HEVC_DXVA2_HWACCEL 0 -#define CONFIG_HEVC_MEDIACODEC_HWACCEL 0 -#define CONFIG_HEVC_QSV_HWACCEL 0 -#define CONFIG_HEVC_VAAPI_HWACCEL 0 -#define CONFIG_HEVC_VDPAU_HWACCEL 0 -#define CONFIG_MJPEG_CUVID_HWACCEL 0 -#define CONFIG_MPEG1_CUVID_HWACCEL 0 -#define CONFIG_MPEG1_XVMC_HWACCEL 0 -#define CONFIG_MPEG1_VDPAU_HWACCEL 0 -#define CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL 0 -#define CONFIG_MPEG2_CUVID_HWACCEL 0 -#define CONFIG_MPEG2_XVMC_HWACCEL 0 -#define CONFIG_MPEG2_D3D11VA_HWACCEL 0 -#define CONFIG_MPEG2_DXVA2_HWACCEL 0 -#define CONFIG_MPEG2_MMAL_HWACCEL 0 -#define CONFIG_MPEG2_QSV_HWACCEL 0 -#define CONFIG_MPEG2_VAAPI_HWACCEL 0 -#define CONFIG_MPEG2_VDPAU_HWACCEL 0 -#define CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL 0 -#define CONFIG_MPEG4_CUVID_HWACCEL 0 -#define CONFIG_MPEG4_MEDIACODEC_HWACCEL 0 -#define CONFIG_MPEG4_MMAL_HWACCEL 0 -#define CONFIG_MPEG4_VAAPI_HWACCEL 0 -#define CONFIG_MPEG4_VDPAU_HWACCEL 0 -#define CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL 0 -#define CONFIG_VC1_CUVID_HWACCEL 0 -#define CONFIG_VC1_D3D11VA_HWACCEL 0 -#define CONFIG_VC1_DXVA2_HWACCEL 0 -#define CONFIG_VC1_VAAPI_HWACCEL 0 -#define CONFIG_VC1_VDPAU_HWACCEL 0 -#define CONFIG_VC1_MMAL_HWACCEL 0 -#define CONFIG_VC1_QSV_HWACCEL 0 -#define CONFIG_VP8_CUVID_HWACCEL 0 -#define CONFIG_VP8_MEDIACODEC_HWACCEL 0 -#define CONFIG_VP9_CUVID_HWACCEL 0 -#define CONFIG_VP9_D3D11VA_HWACCEL 0 -#define CONFIG_VP9_DXVA2_HWACCEL 0 -#define CONFIG_VP9_MEDIACODEC_HWACCEL 0 -#define CONFIG_VP9_VAAPI_HWACCEL 0 -#define CONFIG_WMV3_D3D11VA_HWACCEL 0 -#define CONFIG_WMV3_DXVA2_HWACCEL 0 -#define CONFIG_WMV3_VAAPI_HWACCEL 0 -#define CONFIG_WMV3_VDPAU_HWACCEL 0 -#define CONFIG_ALSA_INDEV 0 -#define CONFIG_AVFOUNDATION_INDEV 0 -#define CONFIG_BKTR_INDEV 0 -#define CONFIG_DECKLINK_INDEV 0 -#define CONFIG_DSHOW_INDEV 0 -#define CONFIG_DV1394_INDEV 0 -#define CONFIG_FBDEV_INDEV 0 -#define CONFIG_GDIGRAB_INDEV 0 -#define CONFIG_IEC61883_INDEV 0 -#define CONFIG_JACK_INDEV 0 -#define CONFIG_LAVFI_INDEV 0 -#define CONFIG_OPENAL_INDEV 0 -#define CONFIG_OSS_INDEV 0 -#define CONFIG_PULSE_INDEV 0 -#define CONFIG_QTKIT_INDEV 0 -#define CONFIG_SNDIO_INDEV 0 -#define CONFIG_V4L2_INDEV 0 -#define CONFIG_VFWCAP_INDEV 0 -#define CONFIG_X11GRAB_INDEV 0 -#define CONFIG_X11GRAB_XCB_INDEV 0 -#define CONFIG_LIBCDIO_INDEV 0 -#define CONFIG_LIBDC1394_INDEV 0 +#define CONFIG_AFIFO_FILTER 1 +#define CONFIG_FIFO_FILTER 1 +#define CONFIG_AA_DEMUXER 0 +#define CONFIG_AAC_DEMUXER 1 +#define CONFIG_AC3_DEMUXER 1 +#define CONFIG_ACM_DEMUXER 0 +#define CONFIG_ACT_DEMUXER 0 +#define CONFIG_ADF_DEMUXER 0 +#define CONFIG_ADP_DEMUXER 0 +#define CONFIG_ADS_DEMUXER 0 +#define CONFIG_ADX_DEMUXER 0 +#define CONFIG_AEA_DEMUXER 0 +#define CONFIG_AFC_DEMUXER 0 +#define CONFIG_AIFF_DEMUXER 0 +#define CONFIG_AIX_DEMUXER 0 +#define CONFIG_AMR_DEMUXER 1 +#define CONFIG_AMRNB_DEMUXER 1 +#define CONFIG_AMRWB_DEMUXER 1 +#define CONFIG_ANM_DEMUXER 0 +#define CONFIG_APC_DEMUXER 0 +#define CONFIG_APE_DEMUXER 1 +#define CONFIG_APNG_DEMUXER 0 +#define CONFIG_APTX_DEMUXER 0 +#define CONFIG_APTX_HD_DEMUXER 0 +#define CONFIG_AQTITLE_DEMUXER 0 +#define CONFIG_ASF_DEMUXER 1 +#define CONFIG_ASF_O_DEMUXER 1 +#define CONFIG_ASS_DEMUXER 0 +#define CONFIG_AST_DEMUXER 0 +#define CONFIG_AU_DEMUXER 0 +#define CONFIG_AVI_DEMUXER 1 +#define CONFIG_AVISYNTH_DEMUXER 0 +#define CONFIG_AVR_DEMUXER 0 +#define CONFIG_AVS_DEMUXER 0 +#define CONFIG_AVS2_DEMUXER 0 +#define CONFIG_BETHSOFTVID_DEMUXER 0 +#define CONFIG_BFI_DEMUXER 0 +#define CONFIG_BINTEXT_DEMUXER 0 +#define CONFIG_BINK_DEMUXER 0 +#define CONFIG_BIT_DEMUXER 0 +#define CONFIG_BMV_DEMUXER 0 +#define CONFIG_BFSTM_DEMUXER 0 +#define CONFIG_BRSTM_DEMUXER 0 +#define CONFIG_BOA_DEMUXER 0 +#define CONFIG_C93_DEMUXER 0 +#define CONFIG_CAF_DEMUXER 0 +#define CONFIG_CAVSVIDEO_DEMUXER 1 +#define CONFIG_CDG_DEMUXER 0 +#define CONFIG_CDXL_DEMUXER 0 +#define CONFIG_CINE_DEMUXER 0 +#define CONFIG_CODEC2_DEMUXER 1 +#define CONFIG_CODEC2RAW_DEMUXER 0 +#define CONFIG_CONCAT_DEMUXER 1 +#define CONFIG_DASH_DEMUXER 0 +#define CONFIG_DATA_DEMUXER 0 +#define CONFIG_DAUD_DEMUXER 0 +#define CONFIG_DCSTR_DEMUXER 0 +#define CONFIG_DFA_DEMUXER 0 +#define CONFIG_DHAV_DEMUXER 0 +#define CONFIG_DIRAC_DEMUXER 0 +#define CONFIG_DNXHD_DEMUXER 1 +#define CONFIG_DSF_DEMUXER 0 +#define CONFIG_DSICIN_DEMUXER 0 +#define CONFIG_DSS_DEMUXER 0 +#define CONFIG_DTS_DEMUXER 0 +#define CONFIG_DTSHD_DEMUXER 0 +#define CONFIG_DV_DEMUXER 0 +#define CONFIG_DVBSUB_DEMUXER 0 +#define CONFIG_DVBTXT_DEMUXER 0 +#define CONFIG_DXA_DEMUXER 0 +#define CONFIG_EA_DEMUXER 0 +#define CONFIG_EA_CDATA_DEMUXER 0 +#define CONFIG_EAC3_DEMUXER 1 +#define CONFIG_EPAF_DEMUXER 0 +#define CONFIG_FFMETADATA_DEMUXER 0 +#define CONFIG_FILMSTRIP_DEMUXER 0 +#define CONFIG_FITS_DEMUXER 0 +#define CONFIG_FLAC_DEMUXER 1 +#define CONFIG_FLIC_DEMUXER 0 +#define CONFIG_FLV_DEMUXER 1 +#define CONFIG_LIVE_FLV_DEMUXER 0 +#define CONFIG_FOURXM_DEMUXER 0 +#define CONFIG_FRM_DEMUXER 0 +#define CONFIG_FSB_DEMUXER 0 +#define CONFIG_G722_DEMUXER 0 +#define CONFIG_G723_1_DEMUXER 0 +#define CONFIG_G726_DEMUXER 0 +#define CONFIG_G726LE_DEMUXER 0 +#define CONFIG_G729_DEMUXER 0 +#define CONFIG_GDV_DEMUXER 0 +#define CONFIG_GENH_DEMUXER 0 +#define CONFIG_GIF_DEMUXER 1 +#define CONFIG_GSM_DEMUXER 0 +#define CONFIG_GXF_DEMUXER 0 +#define CONFIG_H261_DEMUXER 0 +#define CONFIG_H263_DEMUXER 1 +#define CONFIG_H264_DEMUXER 1 +#define CONFIG_HCOM_DEMUXER 0 +#define CONFIG_HEVC_DEMUXER 1 +#define CONFIG_HLS_DEMUXER 1 +#define CONFIG_HNM_DEMUXER 0 +#define CONFIG_ICO_DEMUXER 0 +#define CONFIG_IDCIN_DEMUXER 0 +#define CONFIG_IDF_DEMUXER 0 +#define CONFIG_IFF_DEMUXER 0 +#define CONFIG_IFV_DEMUXER 0 +#define CONFIG_ILBC_DEMUXER 0 +#define CONFIG_IMAGE2_DEMUXER 1 +#define CONFIG_IMAGE2PIPE_DEMUXER 1 +#define CONFIG_IMAGE2_ALIAS_PIX_DEMUXER 0 +#define CONFIG_IMAGE2_BRENDER_PIX_DEMUXER 0 +#define CONFIG_INGENIENT_DEMUXER 0 +#define CONFIG_IPMOVIE_DEMUXER 0 +#define CONFIG_IRCAM_DEMUXER 0 +#define CONFIG_ISS_DEMUXER 0 +#define CONFIG_IV8_DEMUXER 0 +#define CONFIG_IVF_DEMUXER 0 +#define CONFIG_IVR_DEMUXER 0 +#define CONFIG_JACOSUB_DEMUXER 0 +#define CONFIG_JV_DEMUXER 0 +#define CONFIG_KUX_DEMUXER 0 +#define CONFIG_LMLM4_DEMUXER 0 +#define CONFIG_LOAS_DEMUXER 0 +#define CONFIG_LRC_DEMUXER 1 +#define CONFIG_LVF_DEMUXER 0 +#define CONFIG_LXF_DEMUXER 0 +#define CONFIG_M4V_DEMUXER 1 +#define CONFIG_MATROSKA_DEMUXER 1 +#define CONFIG_MGSTS_DEMUXER 0 +#define CONFIG_MICRODVD_DEMUXER 0 +#define CONFIG_MJPEG_DEMUXER 1 +#define CONFIG_MJPEG_2000_DEMUXER 0 +#define CONFIG_MLP_DEMUXER 0 +#define CONFIG_MLV_DEMUXER 0 +#define CONFIG_MM_DEMUXER 0 +#define CONFIG_MMF_DEMUXER 0 +#define CONFIG_MOV_DEMUXER 1 +#define CONFIG_MP3_DEMUXER 1 +#define CONFIG_MPC_DEMUXER 0 +#define CONFIG_MPC8_DEMUXER 0 +#define CONFIG_MPEGPS_DEMUXER 0 +#define CONFIG_MPEGTS_DEMUXER 1 +#define CONFIG_MPEGTSRAW_DEMUXER 0 +#define CONFIG_MPEGVIDEO_DEMUXER 1 +#define CONFIG_MPJPEG_DEMUXER 0 +#define CONFIG_MPL2_DEMUXER 0 +#define CONFIG_MPSUB_DEMUXER 0 +#define CONFIG_MSF_DEMUXER 0 +#define CONFIG_MSNWC_TCP_DEMUXER 0 +#define CONFIG_MTAF_DEMUXER 0 +#define CONFIG_MTV_DEMUXER 0 +#define CONFIG_MUSX_DEMUXER 0 +#define CONFIG_MV_DEMUXER 1 +#define CONFIG_MVI_DEMUXER 0 +#define CONFIG_MXF_DEMUXER 0 +#define CONFIG_MXG_DEMUXER 0 +#define CONFIG_NC_DEMUXER 0 +#define CONFIG_NISTSPHERE_DEMUXER 0 +#define CONFIG_NSP_DEMUXER 0 +#define CONFIG_NSV_DEMUXER 0 +#define CONFIG_NUT_DEMUXER 0 +#define CONFIG_NUV_DEMUXER 0 +#define CONFIG_OGG_DEMUXER 1 +#define CONFIG_OMA_DEMUXER 0 +#define CONFIG_PAF_DEMUXER 0 +#define CONFIG_PCM_ALAW_DEMUXER 0 +#define CONFIG_PCM_MULAW_DEMUXER 0 +#define CONFIG_PCM_VIDC_DEMUXER 0 +#define CONFIG_PCM_F64BE_DEMUXER 0 +#define CONFIG_PCM_F64LE_DEMUXER 0 +#define CONFIG_PCM_F32BE_DEMUXER 0 +#define CONFIG_PCM_F32LE_DEMUXER 0 +#define CONFIG_PCM_S32BE_DEMUXER 0 +#define CONFIG_PCM_S32LE_DEMUXER 0 +#define CONFIG_PCM_S24BE_DEMUXER 0 +#define CONFIG_PCM_S24LE_DEMUXER 0 +#define CONFIG_PCM_S16BE_DEMUXER 0 +#define CONFIG_PCM_S16LE_DEMUXER 0 +#define CONFIG_PCM_S8_DEMUXER 0 +#define CONFIG_PCM_U32BE_DEMUXER 0 +#define CONFIG_PCM_U32LE_DEMUXER 0 +#define CONFIG_PCM_U24BE_DEMUXER 0 +#define CONFIG_PCM_U24LE_DEMUXER 0 +#define CONFIG_PCM_U16BE_DEMUXER 0 +#define CONFIG_PCM_U16LE_DEMUXER 0 +#define CONFIG_PCM_U8_DEMUXER 0 +#define CONFIG_PJS_DEMUXER 0 +#define CONFIG_PMP_DEMUXER 0 +#define CONFIG_PVA_DEMUXER 0 +#define CONFIG_PVF_DEMUXER 0 +#define CONFIG_QCP_DEMUXER 0 +#define CONFIG_R3D_DEMUXER 0 +#define CONFIG_RAWVIDEO_DEMUXER 0 +#define CONFIG_REALTEXT_DEMUXER 1 +#define CONFIG_REDSPARK_DEMUXER 0 +#define CONFIG_RL2_DEMUXER 0 +#define CONFIG_RM_DEMUXER 1 +#define CONFIG_ROQ_DEMUXER 0 +#define CONFIG_RPL_DEMUXER 0 +#define CONFIG_RSD_DEMUXER 0 +#define CONFIG_RSO_DEMUXER 0 +#define CONFIG_RTP_DEMUXER 1 +#define CONFIG_RTSP_DEMUXER 1 +#define CONFIG_S337M_DEMUXER 0 +#define CONFIG_SAMI_DEMUXER 1 +#define CONFIG_SAP_DEMUXER 0 +#define CONFIG_SBC_DEMUXER 0 +#define CONFIG_SBG_DEMUXER 0 +#define CONFIG_SCC_DEMUXER 0 +#define CONFIG_SDP_DEMUXER 1 +#define CONFIG_SDR2_DEMUXER 0 +#define CONFIG_SDS_DEMUXER 0 +#define CONFIG_SDX_DEMUXER 0 +#define CONFIG_SEGAFILM_DEMUXER 0 +#define CONFIG_SER_DEMUXER 0 +#define CONFIG_SHORTEN_DEMUXER 0 +#define CONFIG_SIFF_DEMUXER 0 +#define CONFIG_SLN_DEMUXER 0 +#define CONFIG_SMACKER_DEMUXER 0 +#define CONFIG_SMJPEG_DEMUXER 0 +#define CONFIG_SMUSH_DEMUXER 0 +#define CONFIG_SOL_DEMUXER 0 +#define CONFIG_SOX_DEMUXER 0 +#define CONFIG_SPDIF_DEMUXER 0 +#define CONFIG_SRT_DEMUXER 1 +#define CONFIG_STR_DEMUXER 0 +#define CONFIG_STL_DEMUXER 0 +#define CONFIG_SUBVIEWER1_DEMUXER 0 +#define CONFIG_SUBVIEWER_DEMUXER 0 +#define CONFIG_SUP_DEMUXER 0 +#define CONFIG_SVAG_DEMUXER 0 +#define CONFIG_SWF_DEMUXER 1 +#define CONFIG_TAK_DEMUXER 0 +#define CONFIG_TEDCAPTIONS_DEMUXER 0 +#define CONFIG_THP_DEMUXER 0 +#define CONFIG_THREEDOSTR_DEMUXER 0 +#define CONFIG_TIERTEXSEQ_DEMUXER 0 +#define CONFIG_TMV_DEMUXER 0 +#define CONFIG_TRUEHD_DEMUXER 0 +#define CONFIG_TTA_DEMUXER 0 +#define CONFIG_TXD_DEMUXER 0 +#define CONFIG_TTY_DEMUXER 0 +#define CONFIG_TY_DEMUXER 0 +#define CONFIG_V210_DEMUXER 0 +#define CONFIG_V210X_DEMUXER 0 +#define CONFIG_VAG_DEMUXER 0 +#define CONFIG_VC1_DEMUXER 1 +#define CONFIG_VC1T_DEMUXER 0 +#define CONFIG_VIVIDAS_DEMUXER 0 +#define CONFIG_VIVO_DEMUXER 0 +#define CONFIG_VMD_DEMUXER 0 +#define CONFIG_VOBSUB_DEMUXER 0 +#define CONFIG_VOC_DEMUXER 0 +#define CONFIG_VPK_DEMUXER 0 +#define CONFIG_VPLAYER_DEMUXER 0 +#define CONFIG_VQF_DEMUXER 0 +#define CONFIG_W64_DEMUXER 0 +#define CONFIG_WAV_DEMUXER 1 +#define CONFIG_WC3_DEMUXER 0 +#define CONFIG_WEBM_DASH_MANIFEST_DEMUXER 0 +#define CONFIG_WEBVTT_DEMUXER 0 +#define CONFIG_WSAUD_DEMUXER 0 +#define CONFIG_WSD_DEMUXER 0 +#define CONFIG_WSVQA_DEMUXER 0 +#define CONFIG_WTV_DEMUXER 0 +#define CONFIG_WVE_DEMUXER 0 +#define CONFIG_WV_DEMUXER 0 +#define CONFIG_XA_DEMUXER 0 +#define CONFIG_XBIN_DEMUXER 0 +#define CONFIG_XMV_DEMUXER 1 +#define CONFIG_XVAG_DEMUXER 0 +#define CONFIG_XWMA_DEMUXER 0 +#define CONFIG_YOP_DEMUXER 0 +#define CONFIG_YUV4MPEGPIPE_DEMUXER 0 +#define CONFIG_IMAGE_BMP_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_DDS_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_DPX_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_EXR_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_GIF_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_J2K_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_JPEG_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PAM_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PBM_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PCX_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PGM_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PICTOR_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PNG_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PPM_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_PSD_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_QDRAW_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_SGI_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_SVG_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_TIFF_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_WEBP_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_XPM_PIPE_DEMUXER 0 +#define CONFIG_IMAGE_XWD_PIPE_DEMUXER 0 +#define CONFIG_LIBGME_DEMUXER 0 +#define CONFIG_LIBMODPLUG_DEMUXER 0 +#define CONFIG_LIBOPENMPT_DEMUXER 0 +#define CONFIG_VAPOURSYNTH_DEMUXER 0 #define CONFIG_A64_MUXER 1 #define CONFIG_AC3_MUXER 1 #define CONFIG_ADTS_MUXER 1 @@ -1988,6 +2310,8 @@ #define CONFIG_AIFF_MUXER 1 #define CONFIG_AMR_MUXER 1 #define CONFIG_APNG_MUXER 1 +#define CONFIG_APTX_MUXER 1 +#define CONFIG_APTX_HD_MUXER 1 #define CONFIG_ASF_MUXER 1 #define CONFIG_ASS_MUXER 1 #define CONFIG_AST_MUXER 1 @@ -1995,9 +2319,12 @@ #define CONFIG_AU_MUXER 1 #define CONFIG_AVI_MUXER 1 #define CONFIG_AVM2_MUXER 1 +#define CONFIG_AVS2_MUXER 1 #define CONFIG_BIT_MUXER 1 #define CONFIG_CAF_MUXER 1 #define CONFIG_CAVSVIDEO_MUXER 1 +#define CONFIG_CODEC2_MUXER 1 +#define CONFIG_CODEC2RAW_MUXER 1 #define CONFIG_CRC_MUXER 1 #define CONFIG_DASH_MUXER 1 #define CONFIG_DATA_MUXER 1 @@ -2008,10 +2335,11 @@ #define CONFIG_DV_MUXER 1 #define CONFIG_EAC3_MUXER 1 #define CONFIG_F4V_MUXER 1 -#define CONFIG_FFM_MUXER 1 #define CONFIG_FFMETADATA_MUXER 1 #define CONFIG_FIFO_MUXER 1 +#define CONFIG_FIFO_TEST_MUXER 1 #define CONFIG_FILMSTRIP_MUXER 1 +#define CONFIG_FITS_MUXER 1 #define CONFIG_FLAC_MUXER 1 #define CONFIG_FLV_MUXER 1 #define CONFIG_FRAMECRC_MUXER 1 @@ -2019,6 +2347,8 @@ #define CONFIG_FRAMEMD5_MUXER 1 #define CONFIG_G722_MUXER 1 #define CONFIG_G723_1_MUXER 1 +#define CONFIG_G726_MUXER 1 +#define CONFIG_G726LE_MUXER 1 #define CONFIG_GIF_MUXER 1 #define CONFIG_GSM_MUXER 1 #define CONFIG_GXF_MUXER 1 @@ -2073,6 +2403,7 @@ #define CONFIG_OPUS_MUXER 1 #define CONFIG_PCM_ALAW_MUXER 1 #define CONFIG_PCM_MULAW_MUXER 1 +#define CONFIG_PCM_VIDC_MUXER 1 #define CONFIG_PCM_F64BE_MUXER 1 #define CONFIG_PCM_F64LE_MUXER 1 #define CONFIG_PCM_F32BE_MUXER 1 @@ -2100,6 +2431,9 @@ #define CONFIG_RTP_MPEGTS_MUXER 1 #define CONFIG_RTSP_MUXER 1 #define CONFIG_SAP_MUXER 1 +#define CONFIG_SBC_MUXER 1 +#define CONFIG_SCC_MUXER 1 +#define CONFIG_SEGAFILM_MUXER 1 #define CONFIG_SEGMENT_MUXER 1 #define CONFIG_STREAM_SEGMENT_MUXER 1 #define CONFIG_SINGLEJPEG_MUXER 1 @@ -2109,6 +2443,7 @@ #define CONFIG_SPX_MUXER 1 #define CONFIG_SPDIF_MUXER 1 #define CONFIG_SRT_MUXER 1 +#define CONFIG_SUP_MUXER 1 #define CONFIG_SWF_MUXER 1 #define CONFIG_TEE_MUXER 1 #define CONFIG_TG2_MUXER 1 @@ -2131,56 +2466,6 @@ #define CONFIG_WV_MUXER 1 #define CONFIG_YUV4MPEGPIPE_MUXER 1 #define CONFIG_CHROMAPRINT_MUXER 0 -#define CONFIG_LIBNUT_MUXER 0 -#define CONFIG_ALSA_OUTDEV 0 -#define CONFIG_CACA_OUTDEV 0 -#define CONFIG_DECKLINK_OUTDEV 0 -#define CONFIG_FBDEV_OUTDEV 0 -#define CONFIG_OPENGL_OUTDEV 0 -#define CONFIG_OSS_OUTDEV 0 -#define CONFIG_PULSE_OUTDEV 0 -#define CONFIG_SDL2_OUTDEV 0 -#define CONFIG_SNDIO_OUTDEV 0 -#define CONFIG_V4L2_OUTDEV 0 -#define CONFIG_XV_OUTDEV 0 -#define CONFIG_AAC_PARSER 1 -#define CONFIG_AAC_LATM_PARSER 1 -#define CONFIG_AC3_PARSER 1 -#define CONFIG_ADX_PARSER 1 -#define CONFIG_BMP_PARSER 1 -#define CONFIG_CAVSVIDEO_PARSER 1 -#define CONFIG_COOK_PARSER 1 -#define CONFIG_DCA_PARSER 1 -#define CONFIG_DIRAC_PARSER 1 -#define CONFIG_DNXHD_PARSER 1 -#define CONFIG_DPX_PARSER 1 -#define CONFIG_DVAUDIO_PARSER 1 -#define CONFIG_DVBSUB_PARSER 1 -#define CONFIG_DVDSUB_PARSER 1 -#define CONFIG_DVD_NAV_PARSER 1 -#define CONFIG_FLAC_PARSER 1 -#define CONFIG_G729_PARSER 1 -#define CONFIG_GSM_PARSER 1 -#define CONFIG_H261_PARSER 1 -#define CONFIG_H263_PARSER 1 -#define CONFIG_H264_PARSER 1 -#define CONFIG_HEVC_PARSER 1 -#define CONFIG_MJPEG_PARSER 1 -#define CONFIG_MLP_PARSER 1 -#define CONFIG_MPEG4VIDEO_PARSER 1 -#define CONFIG_MPEGAUDIO_PARSER 1 -#define CONFIG_MPEGVIDEO_PARSER 1 -#define CONFIG_OPUS_PARSER 1 -#define CONFIG_PNG_PARSER 1 -#define CONFIG_PNM_PARSER 1 -#define CONFIG_RV30_PARSER 1 -#define CONFIG_RV40_PARSER 1 -#define CONFIG_TAK_PARSER 1 -#define CONFIG_VC1_PARSER 1 -#define CONFIG_VORBIS_PARSER 1 -#define CONFIG_VP3_PARSER 1 -#define CONFIG_VP8_PARSER 1 -#define CONFIG_VP9_PARSER 1 #define CONFIG_ASYNC_PROTOCOL 1 #define CONFIG_BLURAY_PROTOCOL 0 #define CONFIG_CACHE_PROTOCOL 1 @@ -2201,6 +2486,7 @@ #define CONFIG_MMST_PROTOCOL 1 #define CONFIG_MD5_PROTOCOL 1 #define CONFIG_PIPE_PROTOCOL 1 +#define CONFIG_PROMPEG_PROTOCOL 1 #define CONFIG_RTMP_PROTOCOL 1 #define CONFIG_RTMPE_PROTOCOL 0 #define CONFIG_RTMPS_PROTOCOL 0 @@ -2213,10 +2499,7 @@ #define CONFIG_SUBFILE_PROTOCOL 1 #define CONFIG_TEE_PROTOCOL 1 #define CONFIG_TCP_PROTOCOL 1 -#define CONFIG_TLS_GNUTLS_PROTOCOL 0 -#define CONFIG_TLS_SCHANNEL_PROTOCOL 0 -#define CONFIG_TLS_SECURETRANSPORT_PROTOCOL 0 -#define CONFIG_TLS_OPENSSL_PROTOCOL 0 +#define CONFIG_TLS_PROTOCOL 0 #define CONFIG_UDP_PROTOCOL 1 #define CONFIG_UDPLITE_PROTOCOL 1 #define CONFIG_UNIX_PROTOCOL 1 @@ -2225,6 +2508,7 @@ #define CONFIG_LIBRTMPS_PROTOCOL 0 #define CONFIG_LIBRTMPT_PROTOCOL 0 #define CONFIG_LIBRTMPTE_PROTOCOL 0 +#define CONFIG_LIBSRT_PROTOCOL 0 #define CONFIG_LIBSSH_PROTOCOL 0 #define CONFIG_LIBSMBCLIENT_PROTOCOL 0 #endif /* FFMPEG_CONFIG_H */ diff --git a/app/src/main/cpp/ffmpeg/ffmpeg.c b/app/src/main/cpp/ffmpeg/ffmpeg.c index ea0eef0..c49b1d6 100644 --- a/app/src/main/cpp/ffmpeg/ffmpeg.c +++ b/app/src/main/cpp/ffmpeg/ffmpeg.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #if HAVE_IO_H @@ -46,9 +47,11 @@ #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" #include "libavutil/fifo.h" +#include "libavutil/hwcontext.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" +#include "libavutil/display.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" #include "libavutil/avstring.h" @@ -57,6 +60,7 @@ #include "libavutil/timestamp.h" #include "libavutil/bprint.h" #include "libavutil/time.h" +#include "libavutil/thread.h" #include "libavutil/threadmessage.h" #include "libavcodec/mathops.h" #include "libavformat/os_support.h" @@ -94,10 +98,6 @@ #include #endif -#if HAVE_PTHREADS -#include -#endif - #include #include "ffmpeg.h" @@ -122,16 +122,26 @@ const char *const forced_keyframes_const_names[] = { NULL }; +typedef struct BenchmarkTimeStamps { + int64_t real_usec; + int64_t user_usec; + int64_t sys_usec; +} BenchmarkTimeStamps; + static void do_video_stats(OutputStream *ost, int frame_size); -static int64_t getutime(void); +static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); +static int ifilter_has_all_input_formats(FilterGraph *fg); static int run_as_daemon = 0; static int nb_frames_dup = 0; +static unsigned dup_warning = 1000; static int nb_frames_drop = 0; static int64_t decode_error_stat[2]; -static int current_time; +static int want_sdp = 1; + +static BenchmarkTimeStamps current_time; AVIOContext *progress_avio = NULL; static uint8_t *subtitle_out; @@ -156,7 +166,7 @@ static struct termios oldtty; static int restore_tty; #endif -#if HAVE_PTHREADS +#if HAVE_THREADS static void free_input_threads(void); #endif @@ -199,15 +209,15 @@ static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, } dst += r->y * dst_linesize + r->x * 4; - src = r->pict.data[0]; - pal = (uint32_t *)r->pict.data[1]; + src = r->data[0]; + pal = (uint32_t *)r->data[1]; for (y = 0; y < r->h; y++) { dst2 = (uint32_t *)dst; src2 = src; for (x = 0; x < r->w; x++) *(dst2++) = pal[*(src2++)]; dst += dst_linesize; - src += r->pict.linesize[0]; + src += r->linesize[0]; } } @@ -215,16 +225,21 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts) { AVFrame *frame = ist->sub2video.frame; int i; + int ret; av_assert1(frame->data[0]); ist->sub2video.last_pts = frame->pts = pts; - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame, - AV_BUFFERSRC_FLAG_KEEP_REF | - AV_BUFFERSRC_FLAG_PUSH); + for (i = 0; i < ist->nb_filters; i++) { + ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame, + AV_BUFFERSRC_FLAG_KEEP_REF | + AV_BUFFERSRC_FLAG_PUSH); + if (ret != AVERROR_EOF && ret < 0) + av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n", + av_err2str(ret)); + } } -static void sub2video_update(InputStream *ist, AVSubtitle *sub) +void sub2video_update(InputStream *ist, AVSubtitle *sub) { AVFrame *frame = ist->sub2video.frame; int8_t *dst; @@ -278,7 +293,8 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) continue; - if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0]) + if (pts2 >= ist2->sub2video.end_pts || + (!ist2->sub2video.frame->data[0] && ist2->sub2video.end_pts < INT64_MAX)) sub2video_update(ist2, NULL); for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++) nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter); @@ -290,11 +306,15 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts) static void sub2video_flush(InputStream *ist) { int i; + int ret; if (ist->sub2video.end_pts < INT64_MAX) sub2video_update(ist, NULL); - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + for (i = 0; i < ist->nb_filters; i++) { + ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + if (ret != AVERROR_EOF && ret < 0) + av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n"); + } } /* end of sub2video hack */ @@ -315,20 +335,21 @@ void term_exit(void) static volatile int received_sigterm = 0; static volatile int received_nb_signals = 0; -static volatile int transcode_init_done = 0; +static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0); static volatile int ffmpeg_exited = 0; static int main_return_code = 0; static void sigterm_handler(int sig) { + int ret; received_sigterm = sig; received_nb_signals++; term_exit_sigsafe(); if(received_nb_signals > 3) { - write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n", - strlen("Received > 3 system signals, hard exiting\n")); - + ret = write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n", + strlen("Received > 3 system signals, hard exiting\n")); + if (ret < 0) { /* Do nothing */ }; exit(123); } } @@ -368,7 +389,7 @@ static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) void term_init(void) { #if HAVE_TERMIOS_H - if(!run_as_daemon){ + if (!run_as_daemon && stdin_interaction) { struct termios tty; if (tcgetattr (0, &tty) == 0) { oldtty = tty; @@ -394,6 +415,9 @@ void term_init(void) #ifdef SIGXCPU signal(SIGXCPU, sigterm_handler); #endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); /* Broken pipe (POSIX). */ +#endif #if HAVE_SETCONSOLECTRLHANDLER SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE); #endif @@ -453,7 +477,7 @@ static int read_key(void) static int decode_interrupt_cb(void *ctx) { - return received_nb_signals > transcode_init_done; + return received_nb_signals > atomic_load(&transcode_init_done); } const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; @@ -471,12 +495,32 @@ static void ffmpeg_cleanup(int ret) FilterGraph *fg = filtergraphs[i]; avfilter_graph_free(&fg->graph); for (j = 0; j < fg->nb_inputs; j++) { + while (av_fifo_size(fg->inputs[j]->frame_queue)) { + AVFrame *frame; + av_fifo_generic_read(fg->inputs[j]->frame_queue, &frame, + sizeof(frame), NULL); + av_frame_free(&frame); + } + av_fifo_freep(&fg->inputs[j]->frame_queue); + if (fg->inputs[j]->ist->sub2video.sub_queue) { + while (av_fifo_size(fg->inputs[j]->ist->sub2video.sub_queue)) { + AVSubtitle sub; + av_fifo_generic_read(fg->inputs[j]->ist->sub2video.sub_queue, + &sub, sizeof(sub), NULL); + avsubtitle_free(&sub); + } + av_fifo_freep(&fg->inputs[j]->ist->sub2video.sub_queue); + } + av_buffer_unref(&fg->inputs[j]->hw_frames_ctx); av_freep(&fg->inputs[j]->name); av_freep(&fg->inputs[j]); } av_freep(&fg->inputs); for (j = 0; j < fg->nb_outputs; j++) { av_freep(&fg->outputs[j]->name); + av_freep(&fg->outputs[j]->formats); + av_freep(&fg->outputs[j]->channel_layouts); + av_freep(&fg->outputs[j]->sample_rates); av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); @@ -504,22 +548,17 @@ static void ffmpeg_cleanup(int ret) } for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - AVBitStreamFilterContext *bsfc; if (!ost) continue; - bsfc = ost->bitstream_filters; - while (bsfc) { - AVBitStreamFilterContext *next = bsfc->next; - av_bitstream_filter_close(bsfc); - bsfc = next; - } - ost->bitstream_filters = NULL; + for (j = 0; j < ost->nb_bitstream_filters; j++) + av_bsf_free(&ost->bsf_ctx[j]); + av_freep(&ost->bsf_ctx); + av_frame_free(&ost->filtered_frame); av_frame_free(&ost->last_frame); - - av_parser_close(ost->parser); + av_dict_free(&ost->encoder_opts); av_freep(&ost->forced_keyframes); av_expr_free(ost->forced_keyframes_pexpr); @@ -532,10 +571,20 @@ static void ffmpeg_cleanup(int ret) av_dict_free(&ost->sws_dict); avcodec_free_context(&ost->enc_ctx); + avcodec_parameters_free(&ost->ref_par); + + if (ost->muxing_queue) { + while (av_fifo_size(ost->muxing_queue)) { + AVPacket pkt; + av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + av_fifo_freep(&ost->muxing_queue); + } av_freep(&output_streams[i]); } -#if HAVE_PTHREADS +#if HAVE_THREADS free_input_threads(); #endif for (i = 0; i < nb_input_files; i++) { @@ -552,6 +601,7 @@ static void ffmpeg_cleanup(int ret) av_frame_free(&ist->sub2video.frame); av_freep(&ist->filters); av_freep(&ist->hwaccel_device); + av_freep(&ist->dts_buffer); avcodec_free_context(&ist->dec_ctx); @@ -578,7 +628,7 @@ static void ffmpeg_cleanup(int ret) if (received_sigterm) { av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n", (int) received_sigterm); - } else if (ret && transcode_init_done) { + } else if (ret && atomic_load(&transcode_init_done)) { av_log(NULL, AV_LOG_INFO, "Conversion failed!\n"); } term_exit(); @@ -622,7 +672,7 @@ static void abort_codec_experimental(AVCodec *c, int encoder) static void update_benchmark(const char *fmt, ...) { if (do_benchmark_all) { - int64_t t = getutime(); + BenchmarkTimeStamps t = get_benchmark_time_stamps(); va_list va; char buf[1024]; @@ -630,7 +680,11 @@ static void update_benchmark(const char *fmt, ...) va_start(va, fmt); vsnprintf(buf, sizeof(buf), fmt, va); va_end(va); - av_log(NULL, AV_LOG_INFO, "bench: %8"PRIu64" %s \n", t - current_time, buf); + av_log(NULL, AV_LOG_INFO, + "bench: %8" PRIu64 " user %8" PRIu64 " sys %8" PRIu64 " real %s \n", + t.user_usec - current_time.user_usec, + t.sys_usec - current_time.sys_usec, + t.real_usec - current_time.real_usec, buf); } current_time = t; } @@ -645,39 +699,57 @@ static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, } } -static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) +static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue) { - AVBitStreamFilterContext *bsfc = ost->bitstream_filters; - AVCodecContext *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec; + AVFormatContext *s = of->ctx; + AVStream *st = ost->st; int ret; - if (!ost->st->codec->extradata_size && ost->enc_ctx->extradata_size) { - ost->st->codec->extradata = av_mallocz(ost->enc_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (ost->st->codec->extradata) { - memcpy(ost->st->codec->extradata, ost->enc_ctx->extradata, ost->enc_ctx->extradata_size); - ost->st->codec->extradata_size = ost->enc_ctx->extradata_size; - } - } - - if ((avctx->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) || - (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) - pkt->pts = pkt->dts = AV_NOPTS_VALUE; - /* * Audio encoders may split the packets -- #frames in != #packets out. * But there is no reordering, so we can limit the number of output packets * by simply dropping them here. * Counting encoded video frames needs to be done separately because of - * reordering, see do_video_out() + * reordering, see do_video_out(). + * Do not count the packet when unqueued because it has been counted when queued. */ - if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) { + if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) { if (ost->frame_number >= ost->max_frames) { av_packet_unref(pkt); return; } ost->frame_number++; } - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + + if (!of->header_written) { + AVPacket tmp_pkt = {0}; + /* the muxer is not initialized yet, buffer the packet */ + if (!av_fifo_space(ost->muxing_queue)) { + int new_size = FFMIN(2 * av_fifo_size(ost->muxing_queue), + ost->max_muxing_queue_size); + if (new_size <= av_fifo_size(ost->muxing_queue)) { + av_log(NULL, AV_LOG_ERROR, + "Too many packets buffered for output stream %d:%d.\n", + ost->file_index, ost->st->index); + exit_program(1); + } + ret = av_fifo_realloc2(ost->muxing_queue, new_size); + if (ret < 0) + exit_program(1); + } + ret = av_packet_make_refcounted(pkt); + if (ret < 0) + exit_program(1); + av_packet_move_ref(&tmp_pkt, pkt); + av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL); + return; + } + + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) || + (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) + pkt->pts = pkt->dts = AV_NOPTS_VALUE; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { int i; uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, NULL); @@ -695,18 +767,11 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) if (pkt->duration > 0) av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), - ost->st->time_base); + ost->mux_timebase); } } - if (bsfc) - av_packet_split_side_data(pkt); - - if ((ret = av_apply_bitstream_filters(avctx, pkt, bsfc)) < 0) { - print_error("", ret); - if (exit_on_error) - exit_program(1); - } + av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base); if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { if (pkt->dts != AV_NOPTS_VALUE && @@ -720,28 +785,28 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1) - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1); } - if( - (avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) && - pkt->dts != AV_NOPTS_VALUE && - ost->last_mux_dts != AV_NOPTS_VALUE) { - int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); - if (pkt->dts < max) { - int loglevel = max - pkt->dts > 2 || avctx->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; - av_log(s, loglevel, "Non-monotonous DTS in output stream " - "%d:%d; previous: %"PRId64", current: %"PRId64"; ", - ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); - if (exit_on_error) { - av_log(NULL, AV_LOG_FATAL, "aborting.\n"); - exit_program(1); + if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) && + pkt->dts != AV_NOPTS_VALUE && + !(st->codecpar->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) && + ost->last_mux_dts != AV_NOPTS_VALUE) { + int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); + if (pkt->dts < max) { + int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; + av_log(s, loglevel, "Non-monotonous DTS in output stream " + "%d:%d; previous: %"PRId64", current: %"PRId64"; ", + ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); + if (exit_on_error) { + av_log(NULL, AV_LOG_FATAL, "aborting.\n"); + exit_program(1); + } + av_log(s, loglevel, "changing to %"PRId64". This may result " + "in incorrect timestamps in the output file.\n", + max); + if (pkt->pts >= pkt->dts) + pkt->pts = FFMAX(pkt->pts, max); + pkt->dts = max; + } } - av_log(s, loglevel, "changing to %"PRId64". This may result " - "in incorrect timestamps in the output file.\n", - max); - if(pkt->pts >= pkt->dts) - pkt->pts = FFMAX(pkt->pts, max); - pkt->dts = max; - } - } } ost->last_mux_dts = pkt->dts; @@ -780,6 +845,68 @@ static void close_output_stream(OutputStream *ost) } } +/* + * Send a single packet to the output, applying any bitstream filters + * associated with the output stream. This may result in any number + * of packets actually being written, depending on what bitstream + * filters are applied. The supplied packet is consumed and will be + * blank (as if newly-allocated) when this function returns. + * + * If eof is set, instead indicate EOF to all bitstream filters and + * therefore flush any delayed packets to the output. A blank packet + * must be supplied in this case. + */ +static void output_packet(OutputFile *of, AVPacket *pkt, + OutputStream *ost, int eof) +{ + int ret = 0; + + /* apply the output bitstream filters, if any */ + if (ost->nb_bitstream_filters) { + int idx; + + ret = av_bsf_send_packet(ost->bsf_ctx[0], eof ? NULL : pkt); + if (ret < 0) + goto finish; + + eof = 0; + idx = 1; + while (idx) { + /* get a packet from the previous filter up the chain */ + ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt); + if (ret == AVERROR(EAGAIN)) { + ret = 0; + idx--; + continue; + } else if (ret == AVERROR_EOF) { + eof = 1; + } else if (ret < 0) + goto finish; + + /* send it to the next filter down the chain or to the muxer */ + if (idx < ost->nb_bitstream_filters) { + ret = av_bsf_send_packet(ost->bsf_ctx[idx], eof ? NULL : pkt); + if (ret < 0) + goto finish; + idx++; + eof = 0; + } else if (eof) + goto finish; + else + write_packet(of, pkt, ost, 0); + } + } else if (!eof) + write_packet(of, pkt, ost, 0); + +finish: + if (ret < 0 && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_ERROR, "Error applying bitstream filters to an output " + "packet for stream #%d:%d.\n", ost->file_index, ost->index); + if(exit_on_error) + exit_program(1); + } +} + static int check_recording_time(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -793,12 +920,12 @@ static int check_recording_time(OutputStream *ost) return 1; } -static void do_audio_out(AVFormatContext *s, OutputStream *ost, +static void do_audio_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { AVCodecContext *enc = ost->enc_ctx; AVPacket pkt; - int got_packet = 0; + int ret; av_init_packet(&pkt); pkt.data = NULL; @@ -822,29 +949,39 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, enc->time_base.num, enc->time_base.den); } - if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) { - av_log(NULL, AV_LOG_FATAL, "Audio encoding failed (avcodec_encode_audio2)\n"); - exit_program(1); - } - update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); + ret = avcodec_send_frame(enc, frame); + if (ret < 0) + goto error; + + while (1) { + ret = avcodec_receive_packet(enc, &pkt); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + goto error; + + update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); - if (got_packet) { - av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); + av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:audio " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); + av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base), + av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base)); } - write_frame(s, &pkt, ost); + output_packet(of, &pkt, ost, 0); } + + return; +error: + av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); + exit_program(1); } -static void do_subtitle_out(AVFormatContext *s, +static void do_subtitle_out(OutputFile *of, OutputStream *ost, - InputStream *ist, AVSubtitle *sub) { int subtitle_out_max_size = 1024 * 1024; @@ -911,22 +1048,22 @@ static void do_subtitle_out(AVFormatContext *s, av_init_packet(&pkt); pkt.data = subtitle_out; pkt.size = subtitle_out_size; - pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base); - pkt.duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->st->time_base); + pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); + pkt.duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { /* XXX: the pts correction is handled here. Maybe handling it in the codec would be better */ if (i == 0) - pkt.pts += 90 * sub->start_display_time; + pkt.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); else - pkt.pts += 90 * sub->end_display_time; + pkt.pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); } pkt.dts = pkt.pts; - write_frame(s, &pkt, ost); + output_packet(of, &pkt, ost, 0); } } -static void do_video_out(AVFormatContext *s, +static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *next_picture, double sync_ipts) @@ -934,7 +1071,8 @@ static void do_video_out(AVFormatContext *s, int ret, format_video_sync; AVPacket pkt; AVCodecContext *enc = ost->enc_ctx; - AVCodecContext *mux_enc = ost->st->codec; + AVCodecParameters *mux_par = ost->st->codecpar; + AVRational frame_rate; int nb_frames, nb0_frames, i; double delta, delta0; double duration = 0; @@ -945,19 +1083,20 @@ static void do_video_out(AVFormatContext *s, if (ost->source_index >= 0) ist = input_streams[ost->source_index]; - if (filter->inputs[0]->frame_rate.num > 0 && - filter->inputs[0]->frame_rate.den > 0) - duration = 1/(av_q2d(filter->inputs[0]->frame_rate) * av_q2d(enc->time_base)); + frame_rate = av_buffersink_get_frame_rate(filter); + if (frame_rate.num > 0 && frame_rate.den > 0) + duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); if (!ost->filters_script && !ost->filters && + (nb_filtergraphs == 0 || !filtergraphs[0]->graph_desc) && next_picture && ist && - lrintf(av_frame_get_pkt_duration(next_picture) * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) { - duration = lrintf(av_frame_get_pkt_duration(next_picture) * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)); + lrintf(next_picture->pkt_duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) { + duration = lrintf(next_picture->pkt_duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)); } if (!next_picture) { @@ -975,10 +1114,10 @@ static void do_video_out(AVFormatContext *s, format_video_sync = video_sync_method; if (format_video_sync == VSYNC_AUTO) { - if(!strcmp(s->oformat->name, "avi")) { + if(!strcmp(of->ctx->oformat->name, "avi")) { format_video_sync = VSYNC_VFR; } else - format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; + format_video_sync = (of->ctx->oformat->flags & AVFMT_VARIABLE_FPS) ? ((of->ctx->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; if ( ist && format_video_sync == VSYNC_CFR && input_files[ist->file_index]->ctx->nb_streams == 1 @@ -996,7 +1135,7 @@ static void do_video_out(AVFormatContext *s, format_video_sync != VSYNC_PASSTHROUGH && format_video_sync != VSYNC_DROP) { if (delta0 < -0.6) { - av_log(NULL, AV_LOG_WARNING, "Past duration %f too large\n", -delta0); + av_log(NULL, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); } else av_log(NULL, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); sync_ipts = ost->sync_opts; @@ -1061,54 +1200,34 @@ static void do_video_out(AVFormatContext *s, } nb_frames_dup += nb_frames - (nb0_frames && ost->last_dropped) - (nb_frames > nb0_frames); av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1); + if (nb_frames_dup > dup_warning) { + av_log(NULL, AV_LOG_WARNING, "More than %d frames duplicated\n", dup_warning); + dup_warning *= 10; + } } ost->last_dropped = nb_frames == nb0_frames && next_picture; - /* duplicates frame if needed */ - for (i = 0; i < nb_frames; i++) { - AVFrame *in_picture; - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; - - if (i < nb0_frames && ost->last_frame) { - in_picture = ost->last_frame; - } else - in_picture = next_picture; + /* duplicates frame if needed */ + for (i = 0; i < nb_frames; i++) { + AVFrame *in_picture; + int forced_keyframe = 0; + double pts_time; + av_init_packet(&pkt); + pkt.data = NULL; + pkt.size = 0; - if (!in_picture) - return; + if (i < nb0_frames && ost->last_frame) { + in_picture = ost->last_frame; + } else + in_picture = next_picture; - in_picture->pts = ost->sync_opts; + if (!in_picture) + return; -#if 1 - if (!check_recording_time(ost)) -#else - if (ost->frame_number >= ost->max_frames) -#endif - return; + in_picture->pts = ost->sync_opts; -#if FF_API_LAVF_FMT_RAWPICTURE - if (s->oformat->flags & AVFMT_RAWPICTURE && - enc->codec->id == AV_CODEC_ID_RAWVIDEO) { - /* raw pictures are written as AVPicture structure to - avoid any copies. We support temporarily the older - method. */ - if (in_picture->interlaced_frame) - mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; - else - mux_enc->field_order = AV_FIELD_PROGRESSIVE; - pkt.data = (uint8_t *)in_picture; - pkt.size = sizeof(AVPicture); - pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base); - pkt.flags |= AV_PKT_FLAG_KEY; - - write_frame(s, &pkt, ost); - } else -#endif - { - int got_packet, forced_keyframe = 0; - double pts_time; + if (!check_recording_time(ost)) + return; if (enc->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && ost->top_field_first >= 0) @@ -1116,17 +1235,21 @@ static void do_video_out(AVFormatContext *s, if (in_picture->interlaced_frame) { if (enc->codec->id == AV_CODEC_ID_MJPEG) - mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; + mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; else - mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; } else - mux_enc->field_order = AV_FIELD_PROGRESSIVE; + mux_par->field_order = AV_FIELD_PROGRESSIVE; in_picture->quality = enc->global_quality; in_picture->pict_type = 0; + if (ost->forced_kf_ref_pts == AV_NOPTS_VALUE && + in_picture->pts != AV_NOPTS_VALUE) + ost->forced_kf_ref_pts = in_picture->pts; + pts_time = in_picture->pts != AV_NOPTS_VALUE ? - in_picture->pts * av_q2d(enc->time_base) : NAN; + (in_picture->pts - ost->forced_kf_ref_pts) * av_q2d(enc->time_base) : NAN; if (ost->forced_kf_index < ost->forced_kf_count && in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) { ost->forced_kf_index++; @@ -1174,14 +1297,20 @@ static void do_video_out(AVFormatContext *s, ost->frames_encoded++; - ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet); - update_benchmark("encode_video %d.%d", ost->file_index, ost->index); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); - exit_program(1); - } + ret = avcodec_send_frame(enc, in_picture); + if (ret < 0) + goto error; + // Make sure Closed Captions will not be duplicated + av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC); + + while (1) { + ret = avcodec_receive_packet(enc, &pkt); + update_benchmark("encode_video %d.%d", ost->file_index, ost->index); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + goto error; - if (got_packet) { if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", @@ -1192,35 +1321,34 @@ static void do_video_out(AVFormatContext *s, if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY)) pkt.pts = ost->sync_opts; - av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); + av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); + av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->mux_timebase), + av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->mux_timebase)); } frame_size = pkt.size; - write_frame(s, &pkt, ost); + output_packet(of, &pkt, ost, 0); /* if two pass, output log */ if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } } - } - ost->sync_opts++; - /* - * For video, number of frames in == number of packets out. - * But there may be reordering, so we can't throw away frames on encoder - * flush, we need to limit them here, before they go into encoder. - */ - ost->frame_number++; + ost->sync_opts++; + /* + * For video, number of frames in == number of packets out. + * But there may be reordering, so we can't throw away frames on encoder + * flush, we need to limit them here, before they go into encoder. + */ + ost->frame_number++; - if (vstats_filename && frame_size) - do_video_stats(ost, frame_size); - } + if (vstats_filename && frame_size) + do_video_stats(ost, frame_size); + } if (!ost->last_frame) ost->last_frame = av_frame_alloc(); @@ -1229,6 +1357,11 @@ static void do_video_out(AVFormatContext *s, av_frame_ref(ost->last_frame, next_picture); else av_frame_free(&ost->last_frame); + + return; +error: + av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); + exit_program(1); } static double psnr(double d) @@ -1254,8 +1387,13 @@ static void do_video_stats(OutputStream *ost, int frame_size) enc = ost->enc_ctx; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { frame_number = ost->st->nb_frames; - fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, - ost->quality / (float)FF_QP2LAMBDA); + if (vstats_version <= 1) { + fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } else { + fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); @@ -1274,6 +1412,8 @@ static void do_video_stats(OutputStream *ost, int frame_size) } } +static int init_output_stream(OutputStream *ost, char *error, int error_len); + static void finish_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -1306,10 +1446,20 @@ static int reap_filters(int flush) AVCodecContext *enc = ost->enc_ctx; int ret = 0; - if (!ost->filter) + if (!ost->filter || !ost->filter->graph->graph) continue; filter = ost->filter->filter; + if (!ost->initialized) { + char error[1024] = ""; + ret = init_output_stream(ost, error, sizeof(error)); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", + ost->file_index, ost->index, error); + exit_program(1); + } + } + if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { return AVERROR(ENOMEM); } @@ -1324,8 +1474,8 @@ static int reap_filters(int flush) av_log(NULL, AV_LOG_WARNING, "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); } else if (flush && ret == AVERROR_EOF) { - if (filter->inputs[0]->type == AVMEDIA_TYPE_VIDEO) - do_video_out(of->ctx, ost, NULL, AV_NOPTS_VALUE); + if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) + do_video_out(of, ost, NULL, AV_NOPTS_VALUE); } break; } @@ -1335,25 +1485,24 @@ static int reap_filters(int flush) } if (filtered_frame->pts != AV_NOPTS_VALUE) { int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + AVRational filter_tb = av_buffersink_get_time_base(filter); AVRational tb = enc->time_base; int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); tb.den <<= extra_bits; float_pts = - av_rescale_q(filtered_frame->pts, filter->inputs[0]->time_base, tb) - + av_rescale_q(filtered_frame->pts, filter_tb, tb) - av_rescale_q(start_time, AV_TIME_BASE_Q, tb); float_pts /= 1 << extra_bits; // avoid exact midoints to reduce the chance of rounding differences, this can be removed in case the fps code is changed to work with integers float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); filtered_frame->pts = - av_rescale_q(filtered_frame->pts, filter->inputs[0]->time_base, enc->time_base) - + av_rescale_q(filtered_frame->pts, filter_tb, enc->time_base) - av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); } - //if (ost->source_index >= 0) - // *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold - switch (filter->inputs[0]->type) { + switch (av_buffersink_get_type(filter)) { case AVMEDIA_TYPE_VIDEO: if (!ost->frame_aspect_ratio.num) enc->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; @@ -1365,16 +1514,16 @@ static int reap_filters(int flush) enc->time_base.num, enc->time_base.den); } - do_video_out(of->ctx, ost, filtered_frame, float_pts); + do_video_out(of, ost, filtered_frame, float_pts); break; case AVMEDIA_TYPE_AUDIO: if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && - enc->channels != av_frame_get_channels(filtered_frame)) { + enc->channels != filtered_frame->channels) { av_log(NULL, AV_LOG_ERROR, "Audio filter graph output is not normalized and encoder does not support parameter changes\n"); break; } - do_audio_out(of->ctx, ost, filtered_frame); + do_audio_out(of, ost, filtered_frame); break; default: // TODO support subtitle filters @@ -1407,7 +1556,7 @@ static void print_final_stats(int64_t total_size) } extra_size += ost->enc_ctx->extradata_size; data_size += ost->data_size; - if ( (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) + if ( (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) != AV_CODEC_FLAG_PASS1) pass1_used = 0; } @@ -1433,7 +1582,7 @@ static void print_final_stats(int64_t total_size) uint64_t total_packets = 0, total_size = 0; av_log(NULL, AV_LOG_VERBOSE, "Input file #%d (%s):\n", - i, f->ctx->filename); + i, f->ctx->url); for (j = 0; j < f->nb_streams; j++) { InputStream *ist = input_streams[f->ist_index + j]; @@ -1467,7 +1616,7 @@ static void print_final_stats(int64_t total_size) uint64_t total_packets = 0, total_size = 0; av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n", - i, of->ctx->filename); + i, of->ctx->url); for (j = 0; j < of->ctx->nb_streams; j++) { OutputStream *ost = output_streams[of->ost_index + j]; @@ -1507,8 +1656,7 @@ static void print_final_stats(int64_t total_size) static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time) { - char buf[1024]; - AVBPrint buf_script; + AVBPrint buf, buf_script; OutputStream *ost; AVFormatContext *oc; int64_t total_size; @@ -1520,6 +1668,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti static int64_t last_time = -1; static int qp_histogram[52]; int hours, mins, secs, us; + const char *hours_sign; int ret; float t; @@ -1545,9 +1694,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti if (total_size <= 0) // FIXME improve avio_size() so it works with non seekable output too total_size = avio_tell(oc->pb); - buf[0] = '\0'; vid = 0; - av_bprint_init(&buf_script, 0, 1); + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); + av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC); for (i = 0; i < nb_output_streams; i++) { float q = -1; ost = output_streams[i]; @@ -1556,7 +1705,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti q = ost->quality / (float) FF_QP2LAMBDA; if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q); + av_bprintf(&buf, "q=%2.1f ", q); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", ost->file_index, ost->index, q); } @@ -1565,21 +1714,21 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti frame_number = ost->frame_number; fps = t > 1 ? frame_number / t : 0; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3.*f q=%3.1f ", + av_bprintf(&buf, "frame=%5d fps=%3.*f q=%3.1f ", frame_number, fps < 9.95, fps, q); av_bprintf(&buf_script, "frame=%d\n", frame_number); - av_bprintf(&buf_script, "fps=%.1f\n", fps); + av_bprintf(&buf_script, "fps=%.2f\n", fps); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", ost->file_index, ost->index, q); if (is_last_report) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L"); + av_bprintf(&buf, "L"); if (qp_hist) { int j; int qp = lrintf(q); if (qp >= 0 && qp < FF_ARRAY_ELEMS(qp_histogram)) qp_histogram[qp]++; for (j = 0; j < 32; j++) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", av_log2(qp_histogram[j] + 1)); + av_bprintf(&buf, "%X", av_log2(qp_histogram[j] + 1)); } if ((enc->flags & AV_CODEC_FLAG_PSNR) && (ost->pict_type != AV_PICTURE_TYPE_NONE || is_last_report)) { @@ -1588,7 +1737,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti double scale, scale_sum = 0; double p; char type[3] = { 'Y','U','V' }; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR="); + av_bprintf(&buf, "PSNR="); for (j = 0; j < 3; j++) { if (is_last_report) { error = enc->error[j]; @@ -1602,12 +1751,12 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti error_sum += error; scale_sum += scale; p = psnr(error / scale); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], p); + av_bprintf(&buf, "%c:%2.2f ", type[j], p); av_bprintf(&buf_script, "stream_%d_%d_psnr_%c=%2.2f\n", ost->file_index, ost->index, type[j] | 32, p); } p = psnr(error_sum / scale_sum); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum)); + av_bprintf(&buf, "*:%2.2f ", psnr(error_sum / scale_sum)); av_bprintf(&buf_script, "stream_%d_%d_psnr_all=%2.2f\n", ost->file_index, ost->index, p); } @@ -1627,57 +1776,64 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti secs %= 60; hours = mins / 60; mins %= 60; + hours_sign = (pts < 0) ? "-" : ""; bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1; speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1; - if (total_size < 0) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "size=N/A time="); - else snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "size=%8.0fkB time=", total_size / 1024.0); - if (pts < 0) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "-"); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%02d:%02d:%02d.%02d ", hours, mins, secs, - (100 * us) / AV_TIME_BASE); + if (total_size < 0) av_bprintf(&buf, "size=N/A time="); + else av_bprintf(&buf, "size=%8.0fkB time=", total_size / 1024.0); + if (pts == AV_NOPTS_VALUE) { + av_bprintf(&buf, "N/A "); + } else { + av_bprintf(&buf, "%s%02d:%02d:%02d.%02d ", + hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE); + } if (bitrate < 0) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=N/A"); + av_bprintf(&buf, "bitrate=N/A"); av_bprintf(&buf_script, "bitrate=N/A\n"); }else{ - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=%6.1fkbits/s", bitrate); + av_bprintf(&buf, "bitrate=%6.1fkbits/s", bitrate); av_bprintf(&buf_script, "bitrate=%6.1fkbits/s\n", bitrate); } if (total_size < 0) av_bprintf(&buf_script, "total_size=N/A\n"); else av_bprintf(&buf_script, "total_size=%"PRId64"\n", total_size); - av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts); - av_bprintf(&buf_script, "out_time=%02d:%02d:%02d.%06d\n", - hours, mins, secs, us); + if (pts == AV_NOPTS_VALUE) { + av_bprintf(&buf_script, "out_time_us=N/A\n"); + av_bprintf(&buf_script, "out_time_ms=N/A\n"); + av_bprintf(&buf_script, "out_time=N/A\n"); + } else { + av_bprintf(&buf_script, "out_time_us=%"PRId64"\n", pts); + av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts); + av_bprintf(&buf_script, "out_time=%s%02d:%02d:%02d.%06d\n", + hours_sign, hours, mins, secs, us); + } if (nb_frames_dup || nb_frames_drop) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d", - nb_frames_dup, nb_frames_drop); + av_bprintf(&buf, " dup=%d drop=%d", nb_frames_dup, nb_frames_drop); av_bprintf(&buf_script, "dup_frames=%d\n", nb_frames_dup); av_bprintf(&buf_script, "drop_frames=%d\n", nb_frames_drop); if (speed < 0) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf)," speed=N/A"); + av_bprintf(&buf, " speed=N/A"); av_bprintf(&buf_script, "speed=N/A\n"); } else { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf)," speed=%4.3gx", speed); + av_bprintf(&buf, " speed=%4.3gx", speed); av_bprintf(&buf_script, "speed=%4.3gx\n", speed); } if (print_stats || is_last_report) { const char end = is_last_report ? '\n' : '\r'; if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) { - fprintf(stderr, "%s %c", buf, end); + fprintf(stderr, "%s %c", buf.str, end); } else - av_log(NULL, AV_LOG_INFO, "%s %c", buf, end); + av_log(NULL, AV_LOG_INFO, "%s %c", buf.str, end); - fflush(stderr); + fflush(stderr); } + av_bprint_finalize(&buf, NULL); if (progress_avio) { av_bprintf(&buf_script, "progress=%s\n", @@ -1697,6 +1853,19 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti print_final_stats(total_size); } +static void ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) +{ + // We never got any input. Set a fake format, which will + // come from libavformat. + ifilter->format = par->format; + ifilter->sample_rate = par->sample_rate; + ifilter->channels = par->channels; + ifilter->channel_layout = par->channel_layout; + ifilter->width = par->width; + ifilter->height = par->height; + ifilter->sample_aspect_ratio = par->sample_aspect_ratio; +} + static void flush_encoders(void) { int i, ret; @@ -1704,74 +1873,111 @@ static void flush_encoders(void) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; AVCodecContext *enc = ost->enc_ctx; - AVFormatContext *os = output_files[ost->file_index]->ctx; - int stop_encoding = 0; + OutputFile *of = output_files[ost->file_index]; if (!ost->encoding_needed) continue; + // Try to enable encoding with no input frames. + // Maybe we should just let encoding fail instead. + if (!ost->initialized) { + FilterGraph *fg = ost->filter->graph; + char error[1024] = ""; + + av_log(NULL, AV_LOG_WARNING, + "Finishing stream %d:%d without any data written to it.\n", + ost->file_index, ost->st->index); + + if (ost->filter && !fg->graph) { + int x; + for (x = 0; x < fg->nb_inputs; x++) { + InputFilter *ifilter = fg->inputs[x]; + if (ifilter->format < 0) + ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); + } + + if (!ifilter_has_all_input_formats(fg)) + continue; + + ret = configure_filtergraph(fg); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error configuring filter graph\n"); + exit_program(1); + } + + finish_output_stream(ost); + } + + ret = init_output_stream(ost, error, sizeof(error)); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", + ost->file_index, ost->index, error); + exit_program(1); + } + } + if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) continue; -#if FF_API_LAVF_FMT_RAWPICTURE - if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) + + if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) continue; -#endif for (;;) { - int (*encode)(AVCodecContext*, AVPacket*, const AVFrame*, int*) = NULL; - const char *desc; + const char *desc = NULL; + AVPacket pkt; + int pkt_size; switch (enc->codec_type) { case AVMEDIA_TYPE_AUDIO: - encode = avcodec_encode_audio2; desc = "audio"; break; case AVMEDIA_TYPE_VIDEO: - encode = avcodec_encode_video2; desc = "video"; break; default: - stop_encoding = 1; + av_assert0(0); } - if (encode) { - AVPacket pkt; - int pkt_size; - int got_packet; - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; - - update_benchmark(NULL); - ret = encode(enc, &pkt, NULL, &got_packet); - update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index); + av_init_packet(&pkt); + pkt.data = NULL; + pkt.size = 0; + + update_benchmark(NULL); + + while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) { + ret = avcodec_send_frame(enc, NULL); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n", desc, av_err2str(ret)); exit_program(1); } - if (ost->logfile && enc->stats_out) { - fprintf(ost->logfile, "%s", enc->stats_out); - } - if (!got_packet) { - stop_encoding = 1; - break; - } - if (ost->finished & MUXER_FINISHED) { - av_packet_unref(&pkt); - continue; - } - av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); - pkt_size = pkt.size; - write_frame(os, &pkt, ost); - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { - do_video_stats(ost, pkt_size); - } } - if (stop_encoding) + update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index); + if (ret < 0 && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n", + desc, + av_err2str(ret)); + exit_program(1); + } + if (ost->logfile && enc->stats_out) { + fprintf(ost->logfile, "%s", enc->stats_out); + } + if (ret == AVERROR_EOF) { + output_packet(of, &pkt, ost, 1); break; + } + if (ost->finished & MUXER_FINISHED) { + av_packet_unref(&pkt); + continue; + } + av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); + pkt_size = pkt.size; + output_packet(of, &pkt, ost, 0); + if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { + do_video_stats(ost, pkt_size); + } } } } @@ -1801,12 +2007,17 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p OutputFile *of = output_files[ost->file_index]; InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; - int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); - AVPicture pict; - AVPacket opkt; + int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); + AVPacket opkt = { 0 }; av_init_packet(&opkt); + // EOF: flush output bitstream filters. + if (!pkt) { + output_packet(of, &opkt, ost, 1); + return; + } + if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !ost->copy_initial_nonkeyframes) return; @@ -1842,71 +2053,40 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p ost->sync_opts++; if (pkt->pts != AV_NOPTS_VALUE) - opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; + opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; else opkt.pts = AV_NOPTS_VALUE; if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->st->time_base); + opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); + opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); opkt.dts -= ost_tb_start_time; - if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) { + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) { int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size); if(!duration) duration = ist->dec_ctx->frame_size; opkt.dts = opkt.pts = av_rescale_delta(ist->st->time_base, pkt->dts, (AVRational){1, ist->dec_ctx->sample_rate}, duration, &ist->filter_in_rescale_delta_last, - ost->st->time_base) - ost_tb_start_time; + ost->mux_timebase) - ost_tb_start_time; } - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); + opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); + opkt.flags = pkt->flags; - // FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if ( ost->st->codec->codec_id != AV_CODEC_ID_H264 - && ost->st->codec->codec_id != AV_CODEC_ID_MPEG1VIDEO - && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO - && ost->st->codec->codec_id != AV_CODEC_ID_VC1 - ) { - int ret = av_parser_change(ost->parser, ost->st->codec, - &opkt.data, &opkt.size, - pkt->data, pkt->size, - pkt->flags & AV_PKT_FLAG_KEY); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "av_parser_change failed: %s\n", - av_err2str(ret)); - exit_program(1); - } - if (ret) { - opkt.buf = av_buffer_create(opkt.data, opkt.size, av_buffer_default_free, NULL, 0); - if (!opkt.buf) - exit_program(1); - } - } else { - opkt.data = pkt->data; - opkt.size = pkt->size; - } - av_copy_packet_side_data(&opkt, pkt); -#if FF_API_LAVF_FMT_RAWPICTURE - if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - ost->st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && - (of->ctx->oformat->flags & AVFMT_RAWPICTURE)) { - /* store AVPicture in AVPacket, as expected by the output format */ - int ret = avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "avpicture_fill failed: %s\n", - av_err2str(ret)); + if (pkt->buf) { + opkt.buf = av_buffer_ref(pkt->buf); + if (!opkt.buf) exit_program(1); - } - opkt.data = (uint8_t *)&pict; - opkt.size = sizeof(AVPicture); - opkt.flags |= AV_PKT_FLAG_KEY; } -#endif + opkt.data = pkt->data; + opkt.size = pkt->size; + + av_copy_packet_side_data(&opkt, pkt); - write_frame(of->ctx, &opkt, ost); + output_packet(of, &opkt, ost, 0); } int guess_input_channel_layout(InputStream *ist) @@ -1923,7 +2103,7 @@ int guess_input_channel_layout(InputStream *ist) return 0; av_get_channel_layout_string(layout_name, sizeof(layout_name), dec->channels, dec->channel_layout); - av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream " + av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream " "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name); } return 1; @@ -1937,174 +2117,303 @@ static void check_decode_result(InputStream *ist, int *got_output, int ret) if (ret < 0 && exit_on_error) exit_program(1); - if (exit_on_error && *got_output && ist) { - if (av_frame_get_decode_error_flags(ist->decoded_frame) || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { - av_log(NULL, AV_LOG_FATAL, "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->filename, ist->st->index); - exit_program(1); + if (*got_output && ist) { + if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) { + av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, + "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->url, ist->st->index); + if (exit_on_error) + exit_program(1); } } } -static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) +// Filters can be configured only if the formats of all inputs are known. +static int ifilter_has_all_input_formats(FilterGraph *fg) { - AVFrame *decoded_frame, *f; - AVCodecContext *avctx = ist->dec_ctx; - int i, ret, err = 0, resample_changed; - AVRational decoded_frame_tb; + int i; + for (i = 0; i < fg->nb_inputs; i++) { + if (fg->inputs[i]->format < 0 && (fg->inputs[i]->type == AVMEDIA_TYPE_AUDIO || + fg->inputs[i]->type == AVMEDIA_TYPE_VIDEO)) + return 0; + } + return 1; +} - if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - decoded_frame = ist->decoded_frame; +static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +{ + FilterGraph *fg = ifilter->graph; + int need_reinit, ret, i; - update_benchmark(NULL); - ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt); - update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); + /* determine if the parameters for this input changed */ + need_reinit = ifilter->format != frame->format; - if (ret >= 0 && avctx->sample_rate <= 0) { - av_log(avctx, AV_LOG_ERROR, "Sample rate %d invalid\n", avctx->sample_rate); - ret = AVERROR_INVALIDDATA; + switch (ifilter->ist->st->codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + need_reinit |= ifilter->sample_rate != frame->sample_rate || + ifilter->channels != frame->channels || + ifilter->channel_layout != frame->channel_layout; + break; + case AVMEDIA_TYPE_VIDEO: + need_reinit |= ifilter->width != frame->width || + ifilter->height != frame->height; + break; } - check_decode_result(ist, got_output, ret); + if (!ifilter->ist->reinit_filters && fg->graph) + need_reinit = 0; - if (!*got_output || ret < 0) - return ret; + if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || + (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) + need_reinit = 1; - ist->samples_decoded += decoded_frame->nb_samples; - ist->frames_decoded++; + if (need_reinit) { + ret = ifilter_parameters_from_frame(ifilter, frame); + if (ret < 0) + return ret; + } -#if 1 - /* increment next_dts to use for the case where the input stream does not - have timestamps or there are multiple frames in the packet */ - ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / - avctx->sample_rate; - ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / - avctx->sample_rate; -#endif + /* (re)init the graph if possible, otherwise buffer the frame and return */ + if (need_reinit || !fg->graph) { + for (i = 0; i < fg->nb_inputs; i++) { + if (!ifilter_has_all_input_formats(fg)) { + AVFrame *tmp = av_frame_clone(frame); + if (!tmp) + return AVERROR(ENOMEM); + av_frame_unref(frame); - resample_changed = ist->resample_sample_fmt != decoded_frame->format || - ist->resample_channels != avctx->channels || - ist->resample_channel_layout != decoded_frame->channel_layout || - ist->resample_sample_rate != decoded_frame->sample_rate; - if (resample_changed) { - char layout1[64], layout2[64]; - - if (!guess_input_channel_layout(ist)) { - av_log(NULL, AV_LOG_FATAL, "Unable to find default channel " - "layout for Input Stream #%d.%d\n", ist->file_index, - ist->st->index); - exit_program(1); + if (!av_fifo_space(ifilter->frame_queue)) { + ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); + if (ret < 0) { + av_frame_free(&tmp); + return ret; + } + } + av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); + return 0; + } } - decoded_frame->channel_layout = avctx->channel_layout; - av_get_channel_layout_string(layout1, sizeof(layout1), ist->resample_channels, - ist->resample_channel_layout); - av_get_channel_layout_string(layout2, sizeof(layout2), avctx->channels, - decoded_frame->channel_layout); + ret = reap_filters(1); + if (ret < 0 && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); + return ret; + } - av_log(NULL, AV_LOG_INFO, - "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:%s to rate:%d fmt:%s ch:%d chl:%s\n", - ist->file_index, ist->st->index, - ist->resample_sample_rate, av_get_sample_fmt_name(ist->resample_sample_fmt), - ist->resample_channels, layout1, - decoded_frame->sample_rate, av_get_sample_fmt_name(decoded_frame->format), - avctx->channels, layout2); - - ist->resample_sample_fmt = decoded_frame->format; - ist->resample_sample_rate = decoded_frame->sample_rate; - ist->resample_channel_layout = decoded_frame->channel_layout; - ist->resample_channels = avctx->channels; - - for (i = 0; i < nb_filtergraphs; i++) - if (ist_in_filtergraph(filtergraphs[i], ist)) { - FilterGraph *fg = filtergraphs[i]; - if (configure_filtergraph(fg) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit_program(1); - } - } + ret = configure_filtergraph(fg); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + return ret; + } } - /* if the decoder provides a pts, use it instead of the last packet pts. - the decoder could be delaying output by a packet or more. */ - if (decoded_frame->pts != AV_NOPTS_VALUE) { - ist->dts = ist->next_dts = ist->pts = ist->next_pts = av_rescale_q(decoded_frame->pts, avctx->time_base, AV_TIME_BASE_Q); - decoded_frame_tb = avctx->time_base; - } else if (decoded_frame->pkt_pts != AV_NOPTS_VALUE) { - decoded_frame->pts = decoded_frame->pkt_pts; - decoded_frame_tb = ist->st->time_base; - } else if (pkt->pts != AV_NOPTS_VALUE) { - decoded_frame->pts = pkt->pts; - decoded_frame_tb = ist->st->time_base; - }else { - decoded_frame->pts = ist->dts; - decoded_frame_tb = AV_TIME_BASE_Q; + ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, AV_BUFFERSRC_FLAG_PUSH); + if (ret < 0) { + if (ret != AVERROR_EOF) + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); + return ret; } - pkt->pts = AV_NOPTS_VALUE; - if (decoded_frame->pts != AV_NOPTS_VALUE) - decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, - (AVRational){1, avctx->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, - (AVRational){1, avctx->sample_rate}); - ist->nb_samples = decoded_frame->nb_samples; + + return 0; +} + +static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) +{ + int ret; + + ifilter->eof = 1; + + if (ifilter->filter) { + ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); + if (ret < 0) + return ret; + } else { + // the filtergraph was never configured + if (ifilter->format < 0) + ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); + if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { + av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2. +// There is the following difference: if you got a frame, you must call +// it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0 +// (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet) +static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) +{ + int ret; + + *got_frame = 0; + + if (pkt) { + ret = avcodec_send_packet(avctx, pkt); + // In particular, we don't expect AVERROR(EAGAIN), because we read all + // decoded frames with avcodec_receive_frame() until done. + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } + + ret = avcodec_receive_frame(avctx, frame); + if (ret < 0 && ret != AVERROR(EAGAIN)) + return ret; + if (ret >= 0) + *got_frame = 1; + + return 0; +} + +static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) +{ + int i, ret; + AVFrame *f; + + av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */ for (i = 0; i < ist->nb_filters; i++) { if (i < ist->nb_filters - 1) { f = ist->filter_frame; - err = av_frame_ref(f, decoded_frame); - if (err < 0) + ret = av_frame_ref(f, decoded_frame); + if (ret < 0) break; } else f = decoded_frame; - err = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, - AV_BUFFERSRC_FLAG_PUSH); - if (err == AVERROR_EOF) - err = 0; /* ignore */ - if (err < 0) + ret = ifilter_send_frame(ist->filters[i], f); + if (ret == AVERROR_EOF) + ret = 0; /* ignore */ + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Failed to inject frame into filter network: %s\n", av_err2str(ret)); break; + } + } + return ret; +} + +static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, + int *decode_failed) +{ + AVFrame *decoded_frame; + AVCodecContext *avctx = ist->dec_ctx; + int ret, err = 0; + AVRational decoded_frame_tb; + + if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) + return AVERROR(ENOMEM); + if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) + return AVERROR(ENOMEM); + decoded_frame = ist->decoded_frame; + + update_benchmark(NULL); + ret = decode(avctx, decoded_frame, got_output, pkt); + update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); + if (ret < 0) + *decode_failed = 1; + + if (ret >= 0 && avctx->sample_rate <= 0) { + av_log(avctx, AV_LOG_ERROR, "Sample rate %d invalid\n", avctx->sample_rate); + ret = AVERROR_INVALIDDATA; + } + + if (ret != AVERROR_EOF) + check_decode_result(ist, got_output, ret); + + if (!*got_output || ret < 0) + return ret; + + ist->samples_decoded += decoded_frame->nb_samples; + ist->frames_decoded++; + + /* increment next_dts to use for the case where the input stream does not + have timestamps or there are multiple frames in the packet */ + ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / + avctx->sample_rate; + ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / + avctx->sample_rate; + + if (decoded_frame->pts != AV_NOPTS_VALUE) { + decoded_frame_tb = ist->st->time_base; + } else if (pkt && pkt->pts != AV_NOPTS_VALUE) { + decoded_frame->pts = pkt->pts; + decoded_frame_tb = ist->st->time_base; + }else { + decoded_frame->pts = ist->dts; + decoded_frame_tb = AV_TIME_BASE_Q; } - decoded_frame->pts = AV_NOPTS_VALUE; + if (decoded_frame->pts != AV_NOPTS_VALUE) + decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, + (AVRational){1, avctx->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, + (AVRational){1, avctx->sample_rate}); + ist->nb_samples = decoded_frame->nb_samples; + err = send_frame_to_filters(ist, decoded_frame); av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } -static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) +static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *duration_pts, int eof, + int *decode_failed) { - AVFrame *decoded_frame, *f; - int i, ret = 0, err = 0, resample_changed; + AVFrame *decoded_frame; + int i, ret = 0, err = 0; int64_t best_effort_timestamp; - AVRational *frame_sample_aspect; + int64_t dts = AV_NOPTS_VALUE; + AVPacket avpkt; + + // With fate-indeo3-2, we're getting 0-sized packets before EOF for some + // reason. This seems like a semi-critical bug. Don't trigger EOF, and + // skip the packet. + if (!eof && pkt && pkt->size == 0) + return 0; if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) return AVERROR(ENOMEM); if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) return AVERROR(ENOMEM); decoded_frame = ist->decoded_frame; - pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); + if (ist->dts != AV_NOPTS_VALUE) + dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt) { + avpkt = *pkt; + avpkt.dts = dts; // ffmpeg.c probably shouldn't do this + } + + // The old code used to set dts on the drain packet, which does not work + // with the new API anymore. + if (eof) { + void *new = av_realloc_array(ist->dts_buffer, ist->nb_dts_buffer + 1, sizeof(ist->dts_buffer[0])); + if (!new) + return AVERROR(ENOMEM); + ist->dts_buffer = new; + ist->dts_buffer[ist->nb_dts_buffer++] = dts; + } update_benchmark(NULL); - ret = avcodec_decode_video2(ist->dec_ctx, - decoded_frame, got_output, pkt); + ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt ? &avpkt : NULL); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); + if (ret < 0) + *decode_failed = 1; // The following line may be required in some cases where there is no parser // or the parser does not has_b_frames correctly - if (ist->st->codec->has_b_frames < ist->dec_ctx->has_b_frames) { + if (ist->st->codecpar->video_delay < ist->dec_ctx->has_b_frames) { if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) { - ist->st->codec->has_b_frames = ist->dec_ctx->has_b_frames; + ist->st->codecpar->video_delay = ist->dec_ctx->has_b_frames; } else av_log(ist->dec_ctx, AV_LOG_WARNING, - "has_b_frames is larger in decoder than demuxer %d > %d.\n" + "video_delay is larger in decoder than demuxer %d > %d.\n" "If you want to help, upload a sample " "of this file to ftp://upload.ffmpeg.org/incoming/ " - "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)", + "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n", ist->dec_ctx->has_b_frames, - ist->st->codec->has_b_frames); + ist->st->codecpar->video_delay); } - check_decode_result(ist, got_output, ret); + if (ret != AVERROR_EOF) + check_decode_result(ist, got_output, ret); if (*got_output && ret >= 0) { if (ist->dec_ctx->width != decoded_frame->width || @@ -2135,9 +2444,26 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } ist->hwaccel_retrieved_pix_fmt = decoded_frame->format; - best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame); - if(best_effort_timestamp != AV_NOPTS_VALUE) - ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q); + best_effort_timestamp= decoded_frame->best_effort_timestamp; + *duration_pts = decoded_frame->pkt_duration; + + if (ist->framerate.num) + best_effort_timestamp = ist->cfr_next_pts++; + + if (eof && best_effort_timestamp == AV_NOPTS_VALUE && ist->nb_dts_buffer > 0) { + best_effort_timestamp = ist->dts_buffer[0]; + + for (i = 0; i < ist->nb_dts_buffer - 1; i++) + ist->dts_buffer[i] = ist->dts_buffer[i + 1]; + ist->nb_dts_buffer--; + } + + if(best_effort_timestamp != AV_NOPTS_VALUE) { + int64_t ts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q); + + if (ts != AV_NOPTS_VALUE) + ist->next_pts = ist->pts = ts; + } if (debug_ts) { av_log(NULL, AV_LOG_INFO, "decoder -> ist_index:%d type:video " @@ -2150,55 +2476,10 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) ist->st->time_base.num, ist->st->time_base.den); } - pkt->size = 0; - if (ist->st->sample_aspect_ratio.num) decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; - resample_changed = ist->resample_width != decoded_frame->width || - ist->resample_height != decoded_frame->height || - ist->resample_pix_fmt != decoded_frame->format; - if (resample_changed) { - av_log(NULL, AV_LOG_INFO, - "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", - ist->file_index, ist->st->index, - ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt), - decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format)); - - ist->resample_width = decoded_frame->width; - ist->resample_height = decoded_frame->height; - ist->resample_pix_fmt = decoded_frame->format; - - for (i = 0; i < nb_filtergraphs; i++) { - if (ist_in_filtergraph(filtergraphs[i], ist) && ist->reinit_filters && - configure_filtergraph(filtergraphs[i]) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n"); - exit_program(1); - } - } - } - - frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio"); - for (i = 0; i < ist->nb_filters; i++) { - if (!frame_sample_aspect->num) - *frame_sample_aspect = ist->st->sample_aspect_ratio; - - if (i < ist->nb_filters - 1) { - f = ist->filter_frame; - err = av_frame_ref(f, decoded_frame); - if (err < 0) - break; - } else - f = decoded_frame; - ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, AV_BUFFERSRC_FLAG_PUSH); - if (ret == AVERROR_EOF) { - ret = 0; /* ignore */ - } else if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, - "Failed to inject frame into filter network: %s\n", av_err2str(ret)); - exit_program(1); - } - } + err = send_frame_to_filters(ist, decoded_frame); fail: av_frame_unref(ist->filter_frame); @@ -2206,15 +2487,18 @@ fail: return err < 0 ? err : ret; } -static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) +static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, + int *decode_failed) { AVSubtitle subtitle; + int free_sub = 1; int i, ret = avcodec_decode_subtitle2(ist->dec_ctx, &subtitle, got_output, pkt); check_decode_result(NULL, got_output, ret); if (ret < 0 || !*got_output) { + *decode_failed = 1; if (!pkt->size) sub2video_flush(ist); return ret; @@ -2227,7 +2511,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) 1000, AV_TIME_BASE); if (end < ist->prev_sub.subtitle.end_display_time) { av_log(ist->dec_ctx, AV_LOG_DEBUG, - "Subtitle duration reduced from %d to %d%s\n", + "Subtitle duration reduced from %"PRId32" to %d%s\n", ist->prev_sub.subtitle.end_display_time, end, end <= 0 ? ", dropping it" : ""); ist->prev_sub.subtitle.end_display_time = end; @@ -2243,7 +2527,21 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) if (!*got_output) return ret; - sub2video_update(ist, &subtitle); + if (ist->sub2video.frame) { + sub2video_update(ist, &subtitle); + } else if (ist->nb_filters) { + if (!ist->sub2video.sub_queue) + ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle)); + if (!ist->sub2video.sub_queue) + exit_program(1); + if (!av_fifo_space(ist->sub2video.sub_queue)) { + ret = av_fifo_realloc2(ist->sub2video.sub_queue, 2 * av_fifo_size(ist->sub2video.sub_queue)); + if (ret < 0) + exit_program(1); + } + av_fifo_generic_write(ist->sub2video.sub_queue, &subtitle, sizeof(subtitle), NULL); + free_sub = 0; + } if (!subtitle.num_rects) goto out; @@ -2257,19 +2555,24 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) || ost->enc->type != AVMEDIA_TYPE_SUBTITLE) continue; - do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle); + do_subtitle_out(output_files[ost->file_index], ost, &subtitle); } out: - avsubtitle_free(&subtitle); + if (free_sub) + avsubtitle_free(&subtitle); return ret; } static int send_filter_eof(InputStream *ist) { int i, ret; + /* TODO keep pts also in stream time base to avoid converting back */ + int64_t pts = av_rescale_q_rnd(ist->pts, AV_TIME_BASE_Q, ist->st->time_base, + AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + for (i = 0; i < ist->nb_filters; i++) { - ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); + ret = ifilter_send_eof(ist->filters[i], pts); if (ret < 0) return ret; } @@ -2280,7 +2583,8 @@ static int send_filter_eof(InputStream *ist) static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { int ret = 0, i; - int got_output = 0; + int repeating = 0; + int eof_reached = 0; AVPacket avpkt; if (!ist->saw_first_ts) { @@ -2303,91 +2607,110 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo av_init_packet(&avpkt); avpkt.data = NULL; avpkt.size = 0; - goto handle_eof; } else { avpkt = *pkt; } - if (pkt->dts != AV_NOPTS_VALUE) { + if (pkt && pkt->dts != AV_NOPTS_VALUE) { ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed) ist->next_pts = ist->pts = ist->dts; } // while we have more to decode or while the decoder did output something on EOF - while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) { - int duration; - handle_eof: + while (ist->decoding_needed) { + int64_t duration_dts = 0; + int64_t duration_pts = 0; + int got_output = 0; + int decode_failed = 0; ist->pts = ist->next_pts; ist->dts = ist->next_dts; - if (avpkt.size && avpkt.size != pkt->size && - !(ist->dec->capabilities & AV_CODEC_CAP_SUBFRAMES)) { - av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING, - "Multiple frames in a packet from stream %d\n", pkt->stream_index); - ist->showed_multi_packet_warning = 1; - } - switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - ret = decode_audio (ist, &avpkt, &got_output); + ret = decode_audio (ist, repeating ? NULL : &avpkt, &got_output, + &decode_failed); break; case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, &avpkt, &got_output); - if (avpkt.duration) { - duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q); - } else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) { - int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->dec_ctx->ticks_per_frame; - duration = ((int64_t)AV_TIME_BASE * - ist->dec_ctx->framerate.den * ticks) / - ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame; - } else - duration = 0; + ret = decode_video (ist, repeating ? NULL : &avpkt, &got_output, &duration_pts, !pkt, + &decode_failed); + if (!repeating || !pkt || got_output) { + if (pkt && pkt->duration) { + duration_dts = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); + } else if(ist->dec_ctx->framerate.num != 0 && ist->dec_ctx->framerate.den != 0) { + int ticks= av_stream_get_parser(ist->st) ? av_stream_get_parser(ist->st)->repeat_pict+1 : ist->dec_ctx->ticks_per_frame; + duration_dts = ((int64_t)AV_TIME_BASE * + ist->dec_ctx->framerate.den * ticks) / + ist->dec_ctx->framerate.num / ist->dec_ctx->ticks_per_frame; + } - if(ist->dts != AV_NOPTS_VALUE && duration) { - ist->next_dts += duration; - }else - ist->next_dts = AV_NOPTS_VALUE; + if(ist->dts != AV_NOPTS_VALUE && duration_dts) { + ist->next_dts += duration_dts; + }else + ist->next_dts = AV_NOPTS_VALUE; + } - if (got_output) - ist->next_pts += duration; //FIXME the duration is not correct in some cases + if (got_output) { + if (duration_pts > 0) { + ist->next_pts += av_rescale_q(duration_pts, ist->st->time_base, AV_TIME_BASE_Q); + } else { + ist->next_pts += duration_dts; + } + } break; case AVMEDIA_TYPE_SUBTITLE: - ret = transcode_subtitles(ist, &avpkt, &got_output); + if (repeating) + break; + ret = transcode_subtitles(ist, &avpkt, &got_output, &decode_failed); + if (!pkt && ret >= 0) + ret = AVERROR_EOF; break; default: return -1; } + if (ret == AVERROR_EOF) { + eof_reached = 1; + break; + } + if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", - ist->file_index, ist->st->index, av_err2str(ret)); - if (exit_on_error) + if (decode_failed) { + av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", + ist->file_index, ist->st->index, av_err2str(ret)); + } else { + av_log(NULL, AV_LOG_FATAL, "Error while processing the decoded " + "data for stream #%d:%d\n", ist->file_index, ist->st->index); + } + if (!decode_failed || exit_on_error) exit_program(1); break; } - avpkt.dts= - avpkt.pts= AV_NOPTS_VALUE; + if (got_output) + ist->got_output = 1; - // touch data and size only if not EOF - if (pkt) { - if(ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) - ret = avpkt.size; - avpkt.data += ret; - avpkt.size -= ret; - } - if (!got_output) { - continue; - } - if (got_output && !pkt) + if (!got_output) + break; + + // During draining, we might get multiple output frames in this loop. + // ffmpeg.c does not drain the filter chain on configuration changes, + // which means if we send multiple frames at once to the filters, and + // one of those frames changes configuration, the buffered frames will + // be lost. This can upset certain FATE tests. + // Decode only 1 frame per call on EOF to appease these FATE tests. + // The ideal solution would be to rewrite decoding to use the new + // decoding API in a better way. + if (!pkt) break; + + repeating = 1; } /* after flushing, send an EOF on all the filter inputs attached to the stream */ /* except when looping we need to flush but not to send an EOF */ - if (!pkt && ist->decoding_needed && !got_output && !no_eof) { + if (!pkt && ist->decoding_needed && eof_reached && !no_eof) { int ret = send_filter_eof(ist); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Error marking filters as finished\n"); @@ -2396,12 +2719,17 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } /* handle stream copy */ - if (!ist->decoding_needed) { + if (!ist->decoding_needed && pkt) { ist->dts = ist->next_dts; switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) / - ist->dec_ctx->sample_rate; + av_assert1(pkt->duration >= 0); + if (ist->dec_ctx->sample_rate) { + ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) / + ist->dec_ctx->sample_rate; + } else { + ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); + } break; case AVMEDIA_TYPE_VIDEO: if (ist->framerate.num) { @@ -2422,7 +2750,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->pts = ist->dts; ist->next_pts = ist->next_dts; } - for (i = 0; pkt && i < nb_output_streams; i++) { + for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; if (!check_output_constraints(ist, ost) || ost->encoding_needed) @@ -2431,7 +2759,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo do_streamcopy(ist, ost, pkt); } - return got_output; + return !eof_reached; } static void print_sdp(void) @@ -2440,8 +2768,14 @@ static void print_sdp(void) int i; int j; AVIOContext *sdp_pb; - AVFormatContext **avc = av_malloc_array(nb_output_files, sizeof(*avc)); + AVFormatContext **avc; + + for (i = 0; i < nb_output_files; i++) { + if (!output_files[i]->header_written) + return; + } + avc = av_malloc_array(nb_output_files, sizeof(*avc)); if (!avc) exit_program(1); for (i = 0, j = 0; i < nb_output_files; i++) { @@ -2473,47 +2807,86 @@ fail: av_freep(&avc); } -static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt) -{ - int i; - for (i = 0; hwaccels[i].name; i++) - if (hwaccels[i].pix_fmt == pix_fmt) - return &hwaccels[i]; - return NULL; -} - static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; const enum AVPixelFormat *p; int ret; - for (p = pix_fmts; *p != -1; p++) { + for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); - const HWAccel *hwaccel; + const AVCodecHWConfig *config = NULL; + int i; if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) break; - hwaccel = get_hwaccel(*p); - if (!hwaccel || - (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) || - (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id)) - continue; + if (ist->hwaccel_id == HWACCEL_GENERIC || + ist->hwaccel_id == HWACCEL_AUTO) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(s->codec, i); + if (!config) + break; + if (!(config->methods & + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + if (config->pix_fmt == *p) + break; + } + } + if (config) { + if (config->device_type != ist->hwaccel_device_type) { + // Different hwaccel offered, ignore. + continue; + } - ret = hwaccel->init(s); - if (ret < 0) { - if (ist->hwaccel_id == hwaccel->id) { + ret = hwaccel_decode_init(s); + if (ret < 0) { + if (ist->hwaccel_id == HWACCEL_GENERIC) { + av_log(NULL, AV_LOG_FATAL, + "%s hwaccel requested for input stream #%d:%d, " + "but cannot be initialized.\n", + av_hwdevice_get_type_name(config->device_type), + ist->file_index, ist->st->index); + return AV_PIX_FMT_NONE; + } + continue; + } + } else { + const HWAccel *hwaccel = NULL; + int i; + for (i = 0; hwaccels[i].name; i++) { + if (hwaccels[i].pix_fmt == *p) { + hwaccel = &hwaccels[i]; + break; + } + } + if (!hwaccel) { + // No hwaccel supporting this pixfmt. + continue; + } + if (hwaccel->id != ist->hwaccel_id) { + // Does not match requested hwaccel. + continue; + } + + ret = hwaccel->init(s); + if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s hwaccel requested for input stream #%d:%d, " "but cannot be initialized.\n", hwaccel->name, ist->file_index, ist->st->index); return AV_PIX_FMT_NONE; } - continue; } - ist->active_hwaccel_id = hwaccel->id; - ist->hwaccel_pix_fmt = *p; + + if (ist->hw_frames_ctx) { + s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx); + if (!s->hw_frames_ctx) + return AV_PIX_FMT_NONE; + } + + ist->hwaccel_pix_fmt = *p; break; } @@ -2556,8 +2929,26 @@ static int init_input_stream(int ist_index, char *error, int error_len) av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n"); } + av_dict_set(&ist->decoder_opts, "sub_text_format", "ass", AV_DICT_DONT_OVERWRITE); + + /* Useful for subtitles retiming by lavf (FIXME), skipping samples in + * audio, and video decoders such as cuvid or mediacodec */ + ist->dec_ctx->pkt_timebase = ist->st->time_base; + if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) av_dict_set(&ist->decoder_opts, "threads", "auto", 0); + /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */ + if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC) + av_dict_set(&ist->decoder_opts, "threads", "1", 0); + + ret = hw_device_setup_for_decode(ist); + if (ret < 0) { + snprintf(error, error_len, "Device setup failed for " + "decoder on input stream #%d:%d : %s", + ist->file_index, ist->st->index, av_err2str(ret)); + return ret; + } + if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { if (ret == AVERROR_EXPERIMENTAL) abort_codec_experimental(codec, 0); @@ -2589,95 +2980,242 @@ static int compare_int64(const void *a, const void *b) return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); } -static int init_output_stream(OutputStream *ost, char *error, int error_len) +/* open the muxer when all the streams are initialized */ +static int check_init_output_file(OutputFile *of, int file_index) { - int ret = 0; + int ret, i; - if (ost->encoding_needed) { - AVCodec *codec = ost->enc; - AVCodecContext *dec = NULL; - InputStream *ist; + for (i = 0; i < of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + if (!ost->initialized) + return 0; + } - if ((ist = get_input_stream(ost))) - dec = ist->dec_ctx; - if (dec && dec->subtitle_header) { - /* ASS code assumes this buffer is null terminated so add extra byte. */ - ost->enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1); - if (!ost->enc_ctx->subtitle_header) - return AVERROR(ENOMEM); - memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); - ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size; - } - if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) - av_dict_set(&ost->encoder_opts, "threads", "auto", 0); - if (ost->enc->type == AVMEDIA_TYPE_AUDIO && - !codec->defaults && - !av_dict_get(ost->encoder_opts, "b", NULL, 0) && - !av_dict_get(ost->encoder_opts, "ab", NULL, 0)) - av_dict_set(&ost->encoder_opts, "b", "128000", 0); + of->ctx->interrupt_callback = int_cb; - if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { - if (ret == AVERROR_EXPERIMENTAL) - abort_codec_experimental(codec, 1); - snprintf(error, error_len, - "Error while opening encoder for output stream #%d:%d - " - "maybe incorrect parameters such as bit_rate, rate, width or height", - ost->file_index, ost->index); - return ret; - } - if (ost->enc->type == AVMEDIA_TYPE_AUDIO && - !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) - av_buffersink_set_frame_size(ost->filter->filter, - ost->enc_ctx->frame_size); - assert_avoptions(ost->encoder_opts); - if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000) - av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." - " It takes bits/s as argument, not kbits/s\n"); + ret = avformat_write_header(of->ctx, &of->opts); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Could not write header for output file #%d " + "(incorrect codec parameters ?): %s\n", + file_index, av_err2str(ret)); + return ret; + } + //assert_avoptions(of->opts); + of->header_written = 1; - ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, - "Error initializing the output stream codec context.\n"); - exit_program(1); - } + av_dump_format(of->ctx, file_index, of->ctx->url, 1); - if (ost->enc_ctx->nb_coded_side_data) { - int i; + if (sdp_filename || want_sdp) + print_sdp(); - ost->st->side_data = av_realloc_array(NULL, ost->enc_ctx->nb_coded_side_data, - sizeof(*ost->st->side_data)); - if (!ost->st->side_data) - return AVERROR(ENOMEM); + /* flush the muxing queues */ + for (i = 0; i < of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; - for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { - const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; - AVPacketSideData *sd_dst = &ost->st->side_data[i]; + /* try to improve muxing time_base (only possible if nothing has been written yet) */ + if (!av_fifo_size(ost->muxing_queue)) + ost->mux_timebase = ost->st->time_base; - sd_dst->data = av_malloc(sd_src->size); - if (!sd_dst->data) - return AVERROR(ENOMEM); - memcpy(sd_dst->data, sd_src->data, sd_src->size); - sd_dst->size = sd_src->size; - sd_dst->type = sd_src->type; - ost->st->nb_side_data++; - } + while (av_fifo_size(ost->muxing_queue)) { + AVPacket pkt; + av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); + write_packet(of, &pkt, ost, 1); } + } - // copy timebase while removing common factors - ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); - ost->st->codec->codec= ost->enc_ctx->codec; - } else { - ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts); + return 0; +} + +static int init_output_bsfs(OutputStream *ost) +{ + AVBSFContext *ctx; + int i, ret; + + if (!ost->nb_bitstream_filters) + return 0; + + for (i = 0; i < ost->nb_bitstream_filters; i++) { + ctx = ost->bsf_ctx[i]; + + ret = avcodec_parameters_copy(ctx->par_in, + i ? ost->bsf_ctx[i - 1]->par_out : ost->st->codecpar); + if (ret < 0) + return ret; + + ctx->time_base_in = i ? ost->bsf_ctx[i - 1]->time_base_out : ost->st->time_base; + + ret = av_bsf_init(ctx); if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, - "Error setting up codec context options.\n"); - return ret; + av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", + ost->bsf_ctx[i]->filter->name); + return ret; } - // copy timebase while removing common factors - ost->st->time_base = av_add_q(ost->st->codec->time_base, (AVRational){0, 1}); } - return ret; + ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1]; + ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); + if (ret < 0) + return ret; + + ost->st->time_base = ctx->time_base_out; + + return 0; +} + +static int init_output_stream_streamcopy(OutputStream *ost) +{ + OutputFile *of = output_files[ost->file_index]; + InputStream *ist = get_input_stream(ost); + AVCodecParameters *par_dst = ost->st->codecpar; + AVCodecParameters *par_src = ost->ref_par; + AVRational sar; + int i, ret; + uint32_t codec_tag = par_dst->codec_tag; + + av_assert0(ist && !ost->filter); + + ret = avcodec_parameters_to_context(ost->enc_ctx, ist->st->codecpar); + if (ret >= 0) + ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, + "Error setting up codec context options.\n"); + return ret; + } + + ret = avcodec_parameters_from_context(par_src, ost->enc_ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, + "Error getting reference codec parameters.\n"); + return ret; + } + + if (!codec_tag) { + unsigned int codec_tag_tmp; + if (!of->ctx->oformat->codec_tag || + av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_src->codec_id || + !av_codec_get_tag2(of->ctx->oformat->codec_tag, par_src->codec_id, &codec_tag_tmp)) + codec_tag = par_src->codec_tag; + } + + ret = avcodec_parameters_copy(par_dst, par_src); + if (ret < 0) + return ret; + + par_dst->codec_tag = codec_tag; + + if (!ost->frame_rate.num) + ost->frame_rate = ist->framerate; + ost->st->avg_frame_rate = ost->frame_rate; + + ret = avformat_transfer_internal_stream_timing_info(of->ctx->oformat, ost->st, ist->st, copy_tb); + if (ret < 0) + return ret; + + // copy timebase while removing common factors + if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) + ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); + + // copy estimated duration as a hint to the muxer + if (ost->st->duration <= 0 && ist->st->duration > 0) + ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); + + // copy disposition + ost->st->disposition = ist->st->disposition; + + if (ist->st->nb_side_data) { + for (i = 0; i < ist->st->nb_side_data; i++) { + const AVPacketSideData *sd_src = &ist->st->side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); + } + } + + if (ost->rotate_overridden) { + uint8_t *sd = av_stream_new_side_data(ost->st, AV_PKT_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (sd) + av_display_rotation_set((int32_t *)sd, -ost->rotate_override_value); + } + + switch (par_dst->codec_type) { + case AVMEDIA_TYPE_AUDIO: + if (audio_volume != 256) { + av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n"); + exit_program(1); + } + if((par_dst->block_align == 1 || par_dst->block_align == 1152 || par_dst->block_align == 576) && par_dst->codec_id == AV_CODEC_ID_MP3) + par_dst->block_align= 0; + if(par_dst->codec_id == AV_CODEC_ID_AC3) + par_dst->block_align= 0; + break; + case AVMEDIA_TYPE_VIDEO: + if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option + sar = + av_mul_q(ost->frame_aspect_ratio, + (AVRational){ par_dst->height, par_dst->width }); + av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " + "with stream copy may produce invalid files\n"); + } + else if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = par_src->sample_aspect_ratio; + ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar; + ost->st->avg_frame_rate = ist->st->avg_frame_rate; + ost->st->r_frame_rate = ist->st->r_frame_rate; + break; + } + + ost->mux_timebase = ist->st->time_base; + + return 0; +} + +static void set_encoder_id(OutputFile *of, OutputStream *ost) +{ + AVDictionaryEntry *e; + + uint8_t *encoder_string; + int encoder_string_len; + int format_flags = 0; + int codec_flags = ost->enc_ctx->flags; + + if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) + return; + + e = av_dict_get(of->opts, "fflags", NULL, 0); + if (e) { + const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0); + if (!o) + return; + av_opt_eval_flags(of->ctx, o, e->value, &format_flags); + } + e = av_dict_get(ost->encoder_opts, "flags", NULL, 0); + if (e) { + const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0); + if (!o) + return; + av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags); + } + + encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2; + encoder_string = av_mallocz(encoder_string_len); + if (!encoder_string) + exit_program(1); + + if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & AV_CODEC_FLAG_BITEXACT)) + av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len); + else + av_strlcpy(encoder_string, "Lavc ", encoder_string_len); + av_strlcat(encoder_string, ost->enc->name, encoder_string_len); + av_dict_set(&ost->st->metadata, "encoder", encoder_string, + AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); } static void parse_forced_key_frames(char *kf, OutputStream *ost, @@ -2734,13 +3272,390 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, } - p = next; - } + p = next; + } + + av_assert0(index == size); + qsort(pts, size, sizeof(*pts), compare_int64); + ost->forced_kf_count = size; + ost->forced_kf_pts = pts; +} + +static void init_encoder_time_base(OutputStream *ost, AVRational default_time_base) +{ + InputStream *ist = get_input_stream(ost); + AVCodecContext *enc_ctx = ost->enc_ctx; + AVFormatContext *oc; + + if (ost->enc_timebase.num > 0) { + enc_ctx->time_base = ost->enc_timebase; + return; + } + + if (ost->enc_timebase.num < 0) { + if (ist) { + enc_ctx->time_base = ist->st->time_base; + return; + } + + oc = output_files[ost->file_index]->ctx; + av_log(oc, AV_LOG_WARNING, "Input stream data not available, using default time base\n"); + } + + enc_ctx->time_base = default_time_base; +} + +static int init_output_stream_encode(OutputStream *ost) +{ + InputStream *ist = get_input_stream(ost); + AVCodecContext *enc_ctx = ost->enc_ctx; + AVCodecContext *dec_ctx = NULL; + AVFormatContext *oc = output_files[ost->file_index]->ctx; + int j, ret; + + set_encoder_id(output_files[ost->file_index], ost); + + // Muxers use AV_PKT_DATA_DISPLAYMATRIX to signal rotation. On the other + // hand, the legacy API makes demuxers set "rotate" metadata entries, + // which have to be filtered out to prevent leaking them to output files. + av_dict_set(&ost->st->metadata, "rotate", NULL, 0); + + if (ist) { + ost->st->disposition = ist->st->disposition; + + dec_ctx = ist->dec_ctx; + + enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; + } else { + for (j = 0; j < oc->nb_streams; j++) { + AVStream *st = oc->streams[j]; + if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type) + break; + } + if (j == oc->nb_streams) + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || + ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + ost->st->disposition = AV_DISPOSITION_DEFAULT; + } + + if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { + if (!ost->frame_rate.num) + ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); + if (ist && !ost->frame_rate.num) + ost->frame_rate = ist->framerate; + if (ist && !ost->frame_rate.num) + ost->frame_rate = ist->st->r_frame_rate; + if (ist && !ost->frame_rate.num) { + ost->frame_rate = (AVRational){25, 1}; + av_log(NULL, AV_LOG_WARNING, + "No information " + "about the input framerate is available. Falling " + "back to a default value of 25fps for output stream #%d:%d. Use the -r option " + "if you want a different framerate.\n", + ost->file_index, ost->index); + } + + if (ost->enc->supported_framerates && !ost->force_fps) { + int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); + ost->frame_rate = ost->enc->supported_framerates[idx]; + } + // reduce frame rate for mpeg4 to be within the spec limits + if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { + av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, + ost->frame_rate.num, ost->frame_rate.den, 65535); + } + } + + switch (enc_ctx->codec_type) { + case AVMEDIA_TYPE_AUDIO: + enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); + if (dec_ctx) + enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); + enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); + enc_ctx->channel_layout = av_buffersink_get_channel_layout(ost->filter->filter); + enc_ctx->channels = av_buffersink_get_channels(ost->filter->filter); + + init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); + break; + + case AVMEDIA_TYPE_VIDEO: + init_encoder_time_base(ost, av_inv_q(ost->frame_rate)); + + if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) + enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); + if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH + && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){ + av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" + "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); + } + for (j = 0; j < ost->forced_kf_count; j++) + ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j], + AV_TIME_BASE_Q, + enc_ctx->time_base); + + enc_ctx->width = av_buffersink_get_w(ost->filter->filter); + enc_ctx->height = av_buffersink_get_h(ost->filter->filter); + enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = + ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option + av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) : + av_buffersink_get_sample_aspect_ratio(ost->filter->filter); + + enc_ctx->pix_fmt = av_buffersink_get_format(ost->filter->filter); + if (dec_ctx) + enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); + + enc_ctx->framerate = ost->frame_rate; + + ost->st->avg_frame_rate = ost->frame_rate; + + if (!dec_ctx || + enc_ctx->width != dec_ctx->width || + enc_ctx->height != dec_ctx->height || + enc_ctx->pix_fmt != dec_ctx->pix_fmt) { + enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample; + } + + if (ost->top_field_first == 0) { + enc_ctx->field_order = AV_FIELD_BB; + } else if (ost->top_field_first == 1) { + enc_ctx->field_order = AV_FIELD_TT; + } + + if (ost->forced_keyframes) { + if (!strncmp(ost->forced_keyframes, "expr:", 5)) { + ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5, + forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Invalid force_key_frames expression '%s'\n", ost->forced_keyframes+5); + return ret; + } + ost->forced_keyframes_expr_const_values[FKF_N] = 0; + ost->forced_keyframes_expr_const_values[FKF_N_FORCED] = 0; + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN; + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN; + + // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes', + // parse it only for static kf timings + } else if(strncmp(ost->forced_keyframes, "source", 6)) { + parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx); + } + } + break; + case AVMEDIA_TYPE_SUBTITLE: + enc_ctx->time_base = AV_TIME_BASE_Q; + if (!enc_ctx->width) { + enc_ctx->width = input_streams[ost->source_index]->st->codecpar->width; + enc_ctx->height = input_streams[ost->source_index]->st->codecpar->height; + } + break; + case AVMEDIA_TYPE_DATA: + break; + default: + abort(); + break; + } + + ost->mux_timebase = enc_ctx->time_base; + + return 0; +} + +static int init_output_stream(OutputStream *ost, char *error, int error_len) +{ + int ret = 0; + + if (ost->encoding_needed) { + AVCodec *codec = ost->enc; + AVCodecContext *dec = NULL; + InputStream *ist; + + ret = init_output_stream_encode(ost); + if (ret < 0) + return ret; + + if ((ist = get_input_stream(ost))) + dec = ist->dec_ctx; + if (dec && dec->subtitle_header) { + /* ASS code assumes this buffer is null terminated so add extra byte. */ + ost->enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1); + if (!ost->enc_ctx->subtitle_header) + return AVERROR(ENOMEM); + memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); + ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size; + } + if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) + av_dict_set(&ost->encoder_opts, "threads", "auto", 0); + if (ost->enc->type == AVMEDIA_TYPE_AUDIO && + !codec->defaults && + !av_dict_get(ost->encoder_opts, "b", NULL, 0) && + !av_dict_get(ost->encoder_opts, "ab", NULL, 0)) + av_dict_set(&ost->encoder_opts, "b", "128000", 0); + + if (ost->filter && av_buffersink_get_hw_frames_ctx(ost->filter->filter) && + ((AVHWFramesContext*)av_buffersink_get_hw_frames_ctx(ost->filter->filter)->data)->format == + av_buffersink_get_format(ost->filter->filter)) { + ost->enc_ctx->hw_frames_ctx = av_buffer_ref(av_buffersink_get_hw_frames_ctx(ost->filter->filter)); + if (!ost->enc_ctx->hw_frames_ctx) + return AVERROR(ENOMEM); + } else { + ret = hw_device_setup_for_encode(ost); + if (ret < 0) { + snprintf(error, error_len, "Device setup failed for " + "encoder on output stream #%d:%d : %s", + ost->file_index, ost->index, av_err2str(ret)); + return ret; + } + } + if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && ost->enc->type == AVMEDIA_TYPE_SUBTITLE) { + int input_props = 0, output_props = 0; + AVCodecDescriptor const *input_descriptor = + avcodec_descriptor_get(dec->codec_id); + AVCodecDescriptor const *output_descriptor = + avcodec_descriptor_get(ost->enc_ctx->codec_id); + if (input_descriptor) + input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (output_descriptor) + output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (input_props && output_props && input_props != output_props) { + snprintf(error, error_len, + "Subtitle encoding currently only possible from text to text " + "or bitmap to bitmap"); + return AVERROR_INVALIDDATA; + } + } + + if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(codec, 1); + snprintf(error, error_len, + "Error while opening encoder for output stream #%d:%d - " + "maybe incorrect parameters such as bit_rate, rate, width or height", + ost->file_index, ost->index); + return ret; + } + if (ost->enc->type == AVMEDIA_TYPE_AUDIO && + !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) + av_buffersink_set_frame_size(ost->filter->filter, + ost->enc_ctx->frame_size); + assert_avoptions(ost->encoder_opts); + if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 && + ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */) + av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." + " It takes bits/s as argument, not kbits/s\n"); + + ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, + "Error initializing the output stream codec context.\n"); + exit_program(1); + } + /* + * FIXME: ost->st->codec should't be needed here anymore. + */ + ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); + if (ret < 0) + return ret; + + if (ost->enc_ctx->nb_coded_side_data) { + int i; + + for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) { + const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(ost->st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); + } + } + + /* + * Add global input side data. For now this is naive, and copies it + * from the input stream's global side data. All side data should + * really be funneled over AVFrame and libavfilter, then added back to + * packet side data, and then potentially using the first packet for + * global side data. + */ + if (ist) { + int i; + for (i = 0; i < ist->st->nb_side_data; i++) { + AVPacketSideData *sd = &ist->st->side_data[i]; + uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); + if (!dst) + return AVERROR(ENOMEM); + memcpy(dst, sd->data, sd->size); + if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) + av_display_rotation_set((uint32_t *)dst, 0); + } + } + + // copy timebase while removing common factors + if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) + ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); + + // copy estimated duration as a hint to the muxer + if (ost->st->duration <= 0 && ist && ist->st->duration > 0) + ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); + + ost->st->codec->codec= ost->enc_ctx->codec; + } else if (ost->stream_copy) { + ret = init_output_stream_streamcopy(ost); + if (ret < 0) + return ret; + } + + // parse user provided disposition, and update stream values + if (ost->disposition) { + static const AVOption opts[] = { + { "disposition" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, + { "default" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "flags" }, + { "dub" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "flags" }, + { "original" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "flags" }, + { "comment" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "flags" }, + { "lyrics" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "flags" }, + { "karaoke" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "flags" }, + { "forced" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "flags" }, + { "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" }, + { "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" }, + { "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" }, + { "attached_pic" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "flags" }, + { "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" }, + { "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" }, + { "dependent" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "flags" }, + { "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" }, + { NULL }, + }; + static const AVClass class = { + .class_name = "", + .item_name = av_default_item_name, + .option = opts, + .version = LIBAVUTIL_VERSION_INT, + }; + const AVClass *pclass = &class; + + ret = av_opt_eval_flags(&pclass, &opts[0], ost->disposition, &ost->st->disposition); + if (ret < 0) + return ret; + } + + /* initialize bitstream filters for the output stream + * needs to be done here, because the codec id for streamcopy is not + * known until now */ + ret = init_output_bsfs(ost); + if (ret < 0) + return ret; + + ost->initialized = 1; + + ret = check_init_output_file(output_files[ost->file_index], ost->file_index); + if (ret < 0) + return ret; - av_assert0(index == size); - qsort(pts, size, sizeof(*pts), compare_int64); - ost->forced_kf_count = size; - ost->forced_kf_pts = pts; + return ret; } static void report_new_stream(int input_index, AVPacket *pkt) @@ -2752,53 +3667,12 @@ static void report_new_stream(int input_index, AVPacket *pkt) return; av_log(file->ctx, AV_LOG_WARNING, "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n", - av_get_media_type_string(st->codec->codec_type), + av_get_media_type_string(st->codecpar->codec_type), input_index, pkt->stream_index, pkt->pos, av_ts2timestr(pkt->dts, &st->time_base)); file->nb_streams_warn = pkt->stream_index + 1; } -static void set_encoder_id(OutputFile *of, OutputStream *ost) -{ - AVDictionaryEntry *e; - - uint8_t *encoder_string; - int encoder_string_len; - int format_flags = 0; - int codec_flags = 0; - - if (av_dict_get(ost->st->metadata, "encoder", NULL, 0)) - return; - - e = av_dict_get(of->opts, "fflags", NULL, 0); - if (e) { - const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0); - if (!o) - return; - av_opt_eval_flags(of->ctx, o, e->value, &format_flags); - } - e = av_dict_get(ost->encoder_opts, "flags", NULL, 0); - if (e) { - const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0); - if (!o) - return; - av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags); - } - - encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2; - encoder_string = av_mallocz(encoder_string_len); - if (!encoder_string) - exit_program(1); - - if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & AV_CODEC_FLAG_BITEXACT)) - av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len); - else - av_strlcpy(encoder_string, "Lavc ", encoder_string_len); - av_strlcat(encoder_string, ost->enc->name, encoder_string_len); - av_dict_set(&ost->st->metadata, "encoder", encoder_string, - AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE); -} - static int transcode_init(void) { int ret = 0, i, j, k; @@ -2806,7 +3680,6 @@ static int transcode_init(void) OutputStream *ost; InputStream *ist; char error[1024] = {0}; - int want_sdp = 1; for (i = 0; i < nb_filtergraphs; i++) { FilterGraph *fg = filtergraphs[i]; @@ -2831,389 +3704,6 @@ static int transcode_init(void) input_streams[j + ifile->ist_index]->start = av_gettime_relative(); } - /* for each output stream, we compute the right encoding parameters */ - for (i = 0; i < nb_output_streams; i++) { - AVCodecContext *enc_ctx; - AVCodecContext *dec_ctx = NULL; - ost = output_streams[i]; - oc = output_files[ost->file_index]->ctx; - ist = get_input_stream(ost); - - if (ost->attachment_filename) - continue; - - enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx; - - if (ist) { - dec_ctx = ist->dec_ctx; - - ost->st->disposition = ist->st->disposition; - enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample; - enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; - } else { - for (j=0; jnb_streams; j++) { - AVStream *st = oc->streams[j]; - if (st != ost->st && st->codec->codec_type == enc_ctx->codec_type) - break; - } - if (j == oc->nb_streams) - if (enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO || enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) - ost->st->disposition = AV_DISPOSITION_DEFAULT; - } - - if (ost->stream_copy) { - AVRational sar; - uint64_t extra_size; - - av_assert0(ist && !ost->filter); - - extra_size = (uint64_t)dec_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE; - - if (extra_size > INT_MAX) { - return AVERROR(EINVAL); - } - - /* if stream_copy is selected, no need to decode or encode */ - enc_ctx->codec_id = dec_ctx->codec_id; - enc_ctx->codec_type = dec_ctx->codec_type; - - if (!enc_ctx->codec_tag) { - unsigned int codec_tag; - if (!oc->oformat->codec_tag || - av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id || - !av_codec_get_tag2(oc->oformat->codec_tag, dec_ctx->codec_id, &codec_tag)) - enc_ctx->codec_tag = dec_ctx->codec_tag; - } - - enc_ctx->bit_rate = dec_ctx->bit_rate; - enc_ctx->rc_max_rate = dec_ctx->rc_max_rate; - enc_ctx->rc_buffer_size = dec_ctx->rc_buffer_size; - enc_ctx->field_order = dec_ctx->field_order; - if (dec_ctx->extradata_size) { - enc_ctx->extradata = av_mallocz(extra_size); - if (!enc_ctx->extradata) { - return AVERROR(ENOMEM); - } - memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size); - } - enc_ctx->extradata_size= dec_ctx->extradata_size; - enc_ctx->bits_per_coded_sample = dec_ctx->bits_per_coded_sample; - - enc_ctx->time_base = ist->st->time_base; - /* - * Avi is a special case here because it supports variable fps but - * having the fps and timebase differe significantly adds quite some - * overhead - */ - if(!strcmp(oc->oformat->name, "avi")) { - if ( copy_tb<0 && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(ist->st->time_base) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(dec_ctx->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 - || copy_tb==2){ - enc_ctx->time_base.num = ist->st->r_frame_rate.den; - enc_ctx->time_base.den = 2*ist->st->r_frame_rate.num; - enc_ctx->ticks_per_frame = 2; - } else if ( copy_tb<0 && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->st->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 - || copy_tb==0){ - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - enc_ctx->time_base.den *= 2; - enc_ctx->ticks_per_frame = 2; - } - } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS) - && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp") - && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod") - && strcmp(oc->oformat->name, "f4v") - ) { - if( copy_tb<0 && dec_ctx->time_base.den - && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->st->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 - || copy_tb==0){ - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - } - } - if ( enc_ctx->codec_tag == AV_RL32("tmcd") - && dec_ctx->time_base.num < dec_ctx->time_base.den - && dec_ctx->time_base.num > 0 - && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { - enc_ctx->time_base = dec_ctx->time_base; - } - - if (!ost->frame_rate.num) - ost->frame_rate = ist->framerate; - if(ost->frame_rate.num) - enc_ctx->time_base = av_inv_q(ost->frame_rate); - - av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, - enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); - - if (ist->st->nb_side_data) { - ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data, - sizeof(*ist->st->side_data)); - if (!ost->st->side_data) - return AVERROR(ENOMEM); - - ost->st->nb_side_data = 0; - for (j = 0; j < ist->st->nb_side_data; j++) { - const AVPacketSideData *sd_src = &ist->st->side_data[j]; - AVPacketSideData *sd_dst = &ost->st->side_data[ost->st->nb_side_data]; - - if (ost->rotate_overridden && sd_src->type == AV_PKT_DATA_DISPLAYMATRIX) - continue; - - sd_dst->data = av_malloc(sd_src->size); - if (!sd_dst->data) - return AVERROR(ENOMEM); - memcpy(sd_dst->data, sd_src->data, sd_src->size); - sd_dst->size = sd_src->size; - sd_dst->type = sd_src->type; - ost->st->nb_side_data++; - } - } - - ost->parser = av_parser_init(enc_ctx->codec_id); - - switch (enc_ctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if (audio_volume != 256) { - av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n"); - exit_program(1); - } - enc_ctx->channel_layout = dec_ctx->channel_layout; - enc_ctx->sample_rate = dec_ctx->sample_rate; - enc_ctx->channels = dec_ctx->channels; - enc_ctx->frame_size = dec_ctx->frame_size; - enc_ctx->audio_service_type = dec_ctx->audio_service_type; - enc_ctx->block_align = dec_ctx->block_align; - enc_ctx->initial_padding = dec_ctx->delay; - enc_ctx->profile = dec_ctx->profile; -#if FF_API_AUDIOENC_DELAY - enc_ctx->delay = dec_ctx->delay; -#endif - if((enc_ctx->block_align == 1 || enc_ctx->block_align == 1152 || enc_ctx->block_align == 576) && enc_ctx->codec_id == AV_CODEC_ID_MP3) - enc_ctx->block_align= 0; - if(enc_ctx->codec_id == AV_CODEC_ID_AC3) - enc_ctx->block_align= 0; - break; - case AVMEDIA_TYPE_VIDEO: - enc_ctx->pix_fmt = dec_ctx->pix_fmt; - enc_ctx->width = dec_ctx->width; - enc_ctx->height = dec_ctx->height; - enc_ctx->has_b_frames = dec_ctx->has_b_frames; - if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option - sar = - av_mul_q(ost->frame_aspect_ratio, - (AVRational){ enc_ctx->height, enc_ctx->width }); - av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " - "with stream copy may produce invalid files\n"); - } - else if (ist->st->sample_aspect_ratio.num) - sar = ist->st->sample_aspect_ratio; - else - sar = dec_ctx->sample_aspect_ratio; - ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar; - ost->st->avg_frame_rate = ist->st->avg_frame_rate; - ost->st->r_frame_rate = ist->st->r_frame_rate; - break; - case AVMEDIA_TYPE_SUBTITLE: - enc_ctx->width = dec_ctx->width; - enc_ctx->height = dec_ctx->height; - break; - case AVMEDIA_TYPE_UNKNOWN: - case AVMEDIA_TYPE_DATA: - case AVMEDIA_TYPE_ATTACHMENT: - break; - default: - abort(); - } - } else { - if (!ost->enc) - ost->enc = avcodec_find_encoder(enc_ctx->codec_id); - if (!ost->enc) { - /* should only happen when a default codec is not present. */ - snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d", - avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); - ret = AVERROR(EINVAL); - goto dump_format; - } - - set_encoder_id(output_files[ost->file_index], ost); - -#if CONFIG_LIBMFX - if (qsv_transcode_init(ost)) - exit_program(1); -#endif - - if (!ost->filter && - (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO || - enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) { - FilterGraph *fg; - fg = init_simple_filtergraph(ist, ost); - if (configure_filtergraph(fg)) { - av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n"); - exit_program(1); - } - } - - if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { - if (!ost->frame_rate.num) - ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); - if (ist && !ost->frame_rate.num) - ost->frame_rate = ist->framerate; - if (ist && !ost->frame_rate.num) - ost->frame_rate = ist->st->r_frame_rate; - if (ist && !ost->frame_rate.num) { - ost->frame_rate = (AVRational){25, 1}; - av_log(NULL, AV_LOG_WARNING, - "No information " - "about the input framerate is available. Falling " - "back to a default value of 25fps for output stream #%d:%d. Use the -r option " - "if you want a different framerate.\n", - ost->file_index, ost->index); - } -// ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1}; - if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) { - int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); - ost->frame_rate = ost->enc->supported_framerates[idx]; - } - // reduce frame rate for mpeg4 to be within the spec limits - if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) { - av_reduce(&ost->frame_rate.num, &ost->frame_rate.den, - ost->frame_rate.num, ost->frame_rate.den, 65535); - } - } - - switch (enc_ctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format; - enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate; - enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout; - enc_ctx->channels = avfilter_link_get_channels(ost->filter->filter->inputs[0]); - enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate }; - break; - case AVMEDIA_TYPE_VIDEO: - enc_ctx->time_base = av_inv_q(ost->frame_rate); - if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) - enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base; - if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH - && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){ - av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" - "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); - } - for (j = 0; j < ost->forced_kf_count; j++) - ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j], - AV_TIME_BASE_Q, - enc_ctx->time_base); - - enc_ctx->width = ost->filter->filter->inputs[0]->w; - enc_ctx->height = ost->filter->filter->inputs[0]->h; - enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio = - ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option - av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) : - ost->filter->filter->inputs[0]->sample_aspect_ratio; - if (!strncmp(ost->enc->name, "libx264", 7) && - enc_ctx->pix_fmt == AV_PIX_FMT_NONE && - ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P) - av_log(NULL, AV_LOG_WARNING, - "No pixel format specified, %s for H.264 encoding chosen.\n" - "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", - av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); - if (!strncmp(ost->enc->name, "mpeg2video", 10) && - enc_ctx->pix_fmt == AV_PIX_FMT_NONE && - ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P) - av_log(NULL, AV_LOG_WARNING, - "No pixel format specified, %s for MPEG-2 encoding chosen.\n" - "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", - av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); - enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format; - - ost->st->avg_frame_rate = ost->frame_rate; - - if (!dec_ctx || - enc_ctx->width != dec_ctx->width || - enc_ctx->height != dec_ctx->height || - enc_ctx->pix_fmt != dec_ctx->pix_fmt) { - enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample; - } - - if (ost->forced_keyframes) { - if (!strncmp(ost->forced_keyframes, "expr:", 5)) { - ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5, - forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, - "Invalid force_key_frames expression '%s'\n", ost->forced_keyframes+5); - return ret; - } - ost->forced_keyframes_expr_const_values[FKF_N] = 0; - ost->forced_keyframes_expr_const_values[FKF_N_FORCED] = 0; - ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN; - ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN; - - // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes', - // parse it only for static kf timings - } else if(strncmp(ost->forced_keyframes, "source", 6)) { - parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx); - } - } - break; - case AVMEDIA_TYPE_SUBTITLE: - enc_ctx->time_base = (AVRational){1, 1000}; - if (!enc_ctx->width) { - enc_ctx->width = input_streams[ost->source_index]->st->codec->width; - enc_ctx->height = input_streams[ost->source_index]->st->codec->height; - } - break; - case AVMEDIA_TYPE_DATA: - break; - default: - abort(); - break; - } - } - - if (ost->disposition) { - static const AVOption opts[] = { - { "disposition" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, - { "default" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "flags" }, - { "dub" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "flags" }, - { "original" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "flags" }, - { "comment" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "flags" }, - { "lyrics" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "flags" }, - { "karaoke" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "flags" }, - { "forced" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "flags" }, - { "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" }, - { "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" }, - { "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" }, - { "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" }, - { "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" }, - { "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" }, - { NULL }, - }; - static const AVClass class = { - .class_name = "", - .item_name = av_default_item_name, - .option = opts, - .version = LIBAVUTIL_VERSION_INT, - }; - const AVClass *pclass = &class; - - ret = av_opt_eval_flags(&pclass, &opts[0], ost->disposition, &ost->st->disposition); - if (ret < 0) - goto dump_format; - } - } - - /* open each encoder */ - for (i = 0; i < nb_output_streams; i++) { - ret = init_output_stream(output_streams[i], error, sizeof(error)); - if (ret < 0) - goto dump_format; - } - /* init input streams */ for (i = 0; i < nb_input_streams; i++) if ((ret = init_input_stream(i, error, sizeof(error))) < 0) { @@ -3224,6 +3714,17 @@ static int transcode_init(void) goto dump_format; } + /* open each encoder */ + for (i = 0; i < nb_output_streams; i++) { + // skip streams fed from filtergraphs until we have a frame for them + if (output_streams[i]->filter) + continue; + + ret = init_output_stream(output_streams[i], error, sizeof(error)); + if (ret < 0) + goto dump_format; + } + /* discard unused programs */ for (i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; @@ -3240,38 +3741,24 @@ static int transcode_init(void) } } - /* open files and write file headers */ + /* write headers for files with no streams */ for (i = 0; i < nb_output_files; i++) { oc = output_files[i]->ctx; - oc->interrupt_callback = int_cb; - if ((ret = avformat_write_header(oc, &output_files[i]->opts)) < 0) { - snprintf(error, sizeof(error), - "Could not write header for output file #%d " - "(incorrect codec parameters ?): %s", - i, av_err2str(ret)); - ret = AVERROR(EINVAL); - goto dump_format; - } -// assert_avoptions(output_files[i]->opts); - if (strcmp(oc->oformat->name, "rtp")) { - want_sdp = 0; + if (oc->oformat->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) { + ret = check_init_output_file(output_files[i], i); + if (ret < 0) + goto dump_format; } } dump_format: - /* dump the file output parameters - cannot be done before in case - of stream copy */ - for (i = 0; i < nb_output_files; i++) { - av_dump_format(output_files[i]->ctx, i, output_files[i]->ctx->filename, 1); - } - /* dump the stream mapping */ av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; for (j = 0; j < ist->nb_filters; j++) { - if (ist->filters[j]->graph->graph_desc) { + if (!filtergraph_is_simple(ist->filters[j]->graph)) { av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s", ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?", ist->filters[j]->name); @@ -3292,7 +3779,7 @@ static int transcode_init(void) continue; } - if (ost->filter && ost->filter->graph->graph_desc) { + if (ost->filter && !filtergraph_is_simple(ost->filter->graph)) { /* output from a complex graph */ av_log(NULL, AV_LOG_INFO, " %s", ost->filter->name); if (nb_filtergraphs > 1) @@ -3353,11 +3840,7 @@ static int transcode_init(void) return ret; } - if (sdp_filename || want_sdp) { - print_sdp(); - } - - transcode_init_done = 1; + atomic_store(&transcode_init_done, 1); return 0; } @@ -3405,7 +3888,12 @@ static OutputStream *choose_output(void) av_rescale_q(ost->st->cur_dts, ost->st->time_base, AV_TIME_BASE_Q); if (ost->st->cur_dts == AV_NOPTS_VALUE) - av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid (this is harmless if it occurs once at the start per stream)\n"); + av_log(NULL, AV_LOG_DEBUG, + "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", + ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished); + + if (!ost->initialized && !ost->inputs_done) + return ost; if (!ost->finished && opts < opts_min) { opts_min = opts; @@ -3478,12 +3966,12 @@ static int check_keyboard_interaction(int64_t cur_time) key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0); fprintf(stderr, "Command reply for stream %d: ret:%d res:\n%s", i, ret, buf); } else if (key == 'c') { - fprintf(stderr, "Queing commands only on filters supporting the specific command is unsupported\n"); + fprintf(stderr, "Queuing commands only on filters supporting the specific command is unsupported\n"); ret = AVERROR_PATCHWELCOME; } else { ret = avfilter_graph_queue_command(fg->graph, target, command, arg, 0, time); if (ret < 0) - fprintf(stderr, "Queing command failed with error %s\n", av_err2str(ret)); + fprintf(stderr, "Queuing command failed with error %s\n", av_err2str(ret)); } } } @@ -3498,7 +3986,11 @@ static int check_keyboard_interaction(int64_t cur_time) if(key == 'D') { debug = input_streams[0]->st->codec->debug<<1; if(!debug) debug = 1; - while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash + while(debug & (FF_DEBUG_DCT_COEFF +#if FF_API_DEBUG_MV + |FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE +#endif + )) //unsupported, would just crash debug += debug; }else{ char buf[32]; @@ -3530,7 +4022,7 @@ static int check_keyboard_interaction(int64_t cur_time) "+ increase verbosity\n" "- decrease verbosity\n" "c Send command to first matching filter supporting it\n" - "C Send/Que command to all matching filters\n" + "C Send/Queue command to all matching filters\n" "D cycle through available debug modes\n" "h dump packets/hex press to cycle through the 3 states\n" "q quit\n" @@ -3540,7 +4032,7 @@ static int check_keyboard_interaction(int64_t cur_time) return 0; } -#if HAVE_PTHREADS +#if HAVE_THREADS static void *input_thread(void *arg) { InputFile *f = arg; @@ -3582,49 +4074,63 @@ static void *input_thread(void *arg) return NULL; } +static void free_input_thread(int i) +{ + InputFile *f = input_files[i]; + AVPacket pkt; + + if (!f || !f->in_thread_queue) + return; + av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF); + while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0) + av_packet_unref(&pkt); + + pthread_join(f->thread, NULL); + f->joined = 1; + av_thread_message_queue_free(&f->in_thread_queue); +} + static void free_input_threads(void) { int i; - for (i = 0; i < nb_input_files; i++) { - InputFile *f = input_files[i]; - AVPacket pkt; + for (i = 0; i < nb_input_files; i++) + free_input_thread(i); +} - if (!f || !f->in_thread_queue) - continue; - av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF); - while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0) - av_packet_unref(&pkt); +static int init_input_thread(int i) +{ + int ret; + InputFile *f = input_files[i]; + + if (nb_input_files == 1) + return 0; + + if (f->ctx->pb ? !f->ctx->pb->seekable : + strcmp(f->ctx->iformat->name, "lavfi")) + f->non_blocking = 1; + ret = av_thread_message_queue_alloc(&f->in_thread_queue, + f->thread_queue_size, sizeof(AVPacket)); + if (ret < 0) + return ret; - pthread_join(f->thread, NULL); - f->joined = 1; + if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) { + av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret)); av_thread_message_queue_free(&f->in_thread_queue); + return AVERROR(ret); } + + return 0; } static int init_input_threads(void) { int i, ret; - if (nb_input_files == 1) - return 0; - for (i = 0; i < nb_input_files; i++) { - InputFile *f = input_files[i]; - - if (f->ctx->pb ? !f->ctx->pb->seekable : - strcmp(f->ctx->iformat->name, "lavfi")) - f->non_blocking = 1; - ret = av_thread_message_queue_alloc(&f->in_thread_queue, - f->thread_queue_size, sizeof(AVPacket)); + ret = init_input_thread(i); if (ret < 0) return ret; - - if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) { - av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret)); - av_thread_message_queue_free(&f->in_thread_queue); - return AVERROR(ret); - } } return 0; } @@ -3650,7 +4156,7 @@ static int get_input_packet(InputFile *f, AVPacket *pkt) } } -#if HAVE_PTHREADS +#if HAVE_THREADS if (nb_input_files > 1) return get_input_packet_mt(f, pkt); #endif @@ -3677,7 +4183,7 @@ static void reset_eagain(void) // set duration to max(tmp, duration) in a proper time base and return duration's time_base static AVRational duration_max(int64_t tmp, int64_t *duration, AVRational tmp_time_base, - AVRational time_base) + AVRational time_base) { int ret; @@ -3710,12 +4216,6 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) ist = input_streams[ifile->ist_index + i]; avctx = ist->dec_ctx; - // flush decoders - if (ist->decoding_needed) { - process_input_packet(ist, NULL, 1); - avcodec_flush_buffers(avctx); - } - /* duration is the length of the last frame in a stream * when audio stream is present we don't care about * last video frame length because it's not defined exactly */ @@ -3732,14 +4232,17 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) AVRational sample_rate = {1, avctx->sample_rate}; duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base); - } else + } else { continue; + } } else { if (ist->framerate.num) { - duration = av_rescale_q(1, ist->framerate, ist->st->time_base); + duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); } else if (ist->st->avg_frame_rate.num) { - duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base); - } else duration = 1; + duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base); + } else { + duration = 1; + } } if (!ifile->duration) ifile->time_base = ist->st->time_base; @@ -3769,7 +4272,7 @@ static int process_input(int file_index) AVFormatContext *is; InputStream *ist; AVPacket pkt; - int ret, i, j; + int ret, thread_ret, i, j; int64_t duration; int64_t pkt_dts; @@ -3781,13 +4284,38 @@ static int process_input(int file_index) return ret; } if (ret < 0 && ifile->loop) { - if ((ret = seek_to_start(ifile, is)) < 0) + AVCodecContext *avctx; + for (i = 0; i < ifile->nb_streams; i++) { + ist = input_streams[ifile->ist_index + i]; + avctx = ist->dec_ctx; + if (ist->decoding_needed) { + ret = process_input_packet(ist, NULL, 1); + if (ret>0) + return 0; + avcodec_flush_buffers(avctx); + } + } +#if HAVE_THREADS + free_input_thread(file_index); +#endif + ret = seek_to_start(ifile, is); +#if HAVE_THREADS + thread_ret = init_input_thread(file_index); + if (thread_ret < 0) + return thread_ret; +#endif + if (ret < 0) + av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n"); + else + ret = get_input_packet(ifile, &pkt); + if (ret == AVERROR(EAGAIN)) { + ifile->eagain = 1; return ret; - ret = get_input_packet(ifile, &pkt); + } } if (ret < 0) { if (ret != AVERROR_EOF) { - print_error(is->filename, ret); + print_error(is->url, ret); if (exit_on_error) exit_program(1); } @@ -3835,9 +4363,11 @@ static int process_input(int file_index) if (ist->discard) goto discard_packet; - if (exit_on_error && (pkt.flags & AV_PKT_FLAG_CORRUPT)) { - av_log(NULL, AV_LOG_FATAL, "%s: corrupt input packet in stream %d\n", is->filename, pkt.stream_index); - exit_program(1); + if (pkt.flags & AV_PKT_FLAG_CORRUPT) { + av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, + "%s: corrupt input packet in stream %d\n", is->url, pkt.stream_index); + if (exit_on_error) + exit_program(1); } if (debug_ts) { @@ -3889,15 +4419,14 @@ static int process_input(int file_index) /* add the stream-global side data to the first packet */ if (ist->nb_packets == 1) { - if (ist->st->nb_side_data) - av_packet_split_side_data(&pkt); for (i = 0; i < ist->st->nb_side_data; i++) { AVPacketSideData *src_sd = &ist->st->side_data[i]; uint8_t *dst_data; - if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) + if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) continue; - if (ist->autorotate && src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) + + if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) continue; dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); @@ -3958,7 +4487,10 @@ static int process_input(int file_index) pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) { ifile->ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, - "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", + "timestamp discontinuity for stream #%d:%d " + "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n", + ist->file_index, ist->st->index, ist->st->id, + av_get_media_type_string(ist->dec_ctx->codec_type), delta, ifile->ts_offset); pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); if (pkt.pts != AV_NOPTS_VALUE) @@ -4060,7 +4592,7 @@ static int transcode_from_filter(FilterGraph *graph, InputStream **best_ist) static int transcode_step(void) { OutputStream *ost; - InputStream *ist; + InputStream *ist = NULL; int ret; ost = choose_output(); @@ -4074,11 +4606,43 @@ static int transcode_step(void) return AVERROR_EOF; } - if (ost->filter) { + if (ost->filter && !ost->filter->graph->graph) { + if (ifilter_has_all_input_formats(ost->filter->graph)) { + ret = configure_filtergraph(ost->filter->graph); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n"); + return ret; + } + } + } + + if (ost->filter && ost->filter->graph->graph) { + if (!ost->initialized) { + char error[1024] = {0}; + ret = init_output_stream(ost, error, sizeof(error)); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", + ost->file_index, ost->index, error); + exit_program(1); + } + } if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0) return ret; if (!ist) return 0; + } else if (ost->filter) { + int i; + for (i = 0; i < ost->filter->graph->nb_inputs; i++) { + InputFilter *ifilter = ost->filter->graph->inputs[i]; + if (!ifilter->ist->got_output && !input_files[ifilter->ist->file_index]->eof_reached) { + ist = ifilter->ist; + break; + } + } + if (!ist) { + ost->inputs_done = 1; + return 0; + } } else { av_assert0(ost->source_index >= 0); ist = input_streams[ost->source_index]; @@ -4119,7 +4683,7 @@ static int transcode(void) timer_start = av_gettime_relative(); -#if HAVE_PTHREADS +#if HAVE_THREADS if ((ret = init_input_threads()) < 0) goto fail; #endif @@ -4140,24 +4704,21 @@ static int transcode(void) ret = transcode_step(); if (ret < 0 && ret != AVERROR_EOF) { - char errbuf[128]; - av_strerror(ret, errbuf, sizeof(errbuf)); - - av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf); + av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); break; } /* dump report by using the output first video and audio streams */ print_report(0, timer_start, cur_time); } -#if HAVE_PTHREADS +#if HAVE_THREADS free_input_threads(); #endif /* at the end of stream, we must flush the decoder buffers */ for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; - if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) { + if (!input_files[ist->file_index]->eof_reached) { process_input_packet(ist, NULL, 0); } } @@ -4168,8 +4729,15 @@ static int transcode(void) /* write the trailer if needed and close file */ for (i = 0; i < nb_output_files; i++) { os = output_files[i]->ctx; + if (!output_files[i]->header_written) { + av_log(NULL, AV_LOG_ERROR, + "Nothing was written into output file %d (%s), because " + "at least one of its streams received no packets.\n", + i, os->url); + continue; + } if ((ret = av_write_trailer(os)) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s", os->filename, av_err2str(ret)); + av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", os->url, av_err2str(ret)); if (exit_on_error) exit_program(1); } @@ -4202,11 +4770,14 @@ static int transcode(void) } } + av_buffer_unref(&hw_device_ctx); + hw_device_free_all(); + /* finished ! */ ret = 0; fail: -#if HAVE_PTHREADS +#if HAVE_THREADS free_input_threads(); #endif @@ -4234,23 +4805,30 @@ static int transcode(void) return ret; } - -static int64_t getutime(void) +static BenchmarkTimeStamps get_benchmark_time_stamps(void) { + BenchmarkTimeStamps time_stamps = { av_gettime_relative() }; #if HAVE_GETRUSAGE struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); - return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec; + time_stamps.user_usec = + (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec; + time_stamps.sys_usec = + (rusage.ru_stime.tv_sec * 1000000LL) + rusage.ru_stime.tv_usec; #elif HAVE_GETPROCESSTIMES HANDLE proc; FILETIME c, e, k, u; proc = GetCurrentProcess(); GetProcessTimes(proc, &c, &e, &k, &u); - return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10; + time_stamps.user_usec = + ((int64_t)u.dwHighDateTime << 32 | u.dwLowDateTime) / 10; + time_stamps.sys_usec = + ((int64_t)k.dwHighDateTime << 32 | k.dwLowDateTime) / 10; #else - return av_gettime_relative(); + time_stamps.user_usec = time_stamps.sys_usec = 0; #endif + return time_stamps; } static int64_t getmaxrss(void) @@ -4277,9 +4855,10 @@ static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl) int run(int argc, char **argv) { - int ret; - int64_t ti; + int i, ret; + BenchmarkTimeStamps ti; main_return_code = 0; + init_dynload(); register_exit(ffmpeg_cleanup); @@ -4300,18 +4879,13 @@ int run(int argc, char **argv) argv++; } - avcodec_register_all(); #if CONFIG_AVDEVICE avdevice_register_all(); #endif - avfilter_register_all(); - av_register_all(); avformat_network_init(); show_banner(argc, argv, options); - term_init(); - /* parse options and open all input/output files */ ret = ffmpeg_parse_options(argc, argv); if (ret < 0) @@ -4329,12 +4903,23 @@ int run(int argc, char **argv) exit_program(1); } - current_time = ti = getutime(); + for (i = 0; i < nb_output_files; i++) { + if (strcmp(output_files[i]->ctx->oformat->name, "rtp")) + want_sdp = 0; + } + + current_time = ti = get_benchmark_time_stamps(); if (transcode() < 0) exit_program(1); - ti = getutime() - ti; if (do_benchmark) { - av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0); + int64_t utime, stime, rtime; + current_time = get_benchmark_time_stamps(); + utime = current_time.user_usec - ti.user_usec; + stime = current_time.sys_usec - ti.sys_usec; + rtime = current_time.real_usec - ti.real_usec; + av_log(NULL, AV_LOG_INFO, + "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n", + utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0); } av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n", decode_error_stat[0], decode_error_stat[1]); diff --git a/app/src/main/cpp/ffmpeg/ffmpeg.h b/app/src/main/cpp/ffmpeg/ffmpeg.h index 4bbc744..e376704 100644 --- a/app/src/main/cpp/ffmpeg/ffmpeg.h +++ b/app/src/main/cpp/ffmpeg/ffmpeg.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef FFMPEG_H -#define FFMPEG_H +#ifndef FFTOOLS_FFMPEG_H +#define FFTOOLS_FFMPEG_H #include "config.h" @@ -25,10 +25,6 @@ #include #include -#if HAVE_PTHREADS -#include -#endif - #include "cmdutils.h" #include "libavformat/avformat.h" @@ -42,8 +38,10 @@ #include "libavutil/dict.h" #include "libavutil/eval.h" #include "libavutil/fifo.h" +#include "libavutil/hwcontext.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" +#include "libavutil/thread.h" #include "libavutil/threadmessage.h" #include "libswresample/swresample.h" @@ -60,11 +58,10 @@ enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, - HWACCEL_VDPAU, - HWACCEL_DXVA2, - HWACCEL_VDA, + HWACCEL_GENERIC, HWACCEL_VIDEOTOOLBOX, HWACCEL_QSV, + HWACCEL_CUVID, }; typedef struct HWAccel { @@ -74,6 +71,12 @@ typedef struct HWAccel { enum AVPixelFormat pix_fmt; } HWAccel; +typedef struct HWDevice { + const char *name; + enum AVHWDeviceType type; + AVBufferRef *device_ref; +} HWDevice; + /* select an input stream for an output stream */ typedef struct StreamMap { int disabled; /* 1 is this mapping is disabled by a negative map */ @@ -126,6 +129,8 @@ typedef struct OptionsContext { int nb_hwaccels; SpecifierOpt *hwaccel_devices; int nb_hwaccel_devices; + SpecifierOpt *hwaccel_output_formats; + int nb_hwaccel_output_formats; SpecifierOpt *autorotate; int nb_autorotate; @@ -148,6 +153,7 @@ typedef struct OptionsContext { float mux_preload; float mux_max_delay; int shortest; + int bitexact; int video_disable; int audio_disable; @@ -208,6 +214,8 @@ typedef struct OptionsContext { int nb_pass; SpecifierOpt *passlogfiles; int nb_passlogfiles; + SpecifierOpt *max_muxing_queue_size; + int nb_max_muxing_queue_size; SpecifierOpt *guess_layout_max; int nb_guess_layout_max; SpecifierOpt *apad; @@ -218,6 +226,10 @@ typedef struct OptionsContext { int nb_disposition; SpecifierOpt *program; int nb_program; + SpecifierOpt *time_bases; + int nb_time_bases; + SpecifierOpt *enc_time_bases; + int nb_enc_time_bases; } OptionsContext; typedef struct InputFilter { @@ -225,6 +237,23 @@ typedef struct InputFilter { struct InputStream *ist; struct FilterGraph *graph; uint8_t *name; + enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video + + AVFifoBuffer *frame_queue; + + // parameters configured for this input + int format; + + int width, height; + AVRational sample_aspect_ratio; + + int sample_rate; + int channels; + uint64_t channel_layout; + + AVBufferRef *hw_frames_ctx; + + int eof; } InputFilter; typedef struct OutputFilter { @@ -236,6 +265,18 @@ typedef struct OutputFilter { /* temporary storage until stream maps are processed */ AVFilterInOut *out_tmp; enum AVMediaType type; + + /* desired output stream properties */ + int width, height; + AVRational frame_rate; + int format; + int sample_rate; + uint64_t channel_layout; + + // those are only set if no format is specified and the encoder gives us multiple options + int *formats; + uint64_t *channel_layouts; + int *sample_rates; } OutputFilter; typedef struct FilterGraph { @@ -279,25 +320,21 @@ typedef struct InputStream { int64_t min_pts; /* pts with the smallest value in a current stream */ int64_t max_pts; /* pts with the higher value in a current stream */ + + // when forcing constant input framerate through -r, + // this contains the pts that will be given to the next decoded frame + int64_t cfr_next_pts; + int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ double ts_scale; int saw_first_ts; - int showed_multi_packet_warning; AVDictionary *decoder_opts; AVRational framerate; /* framerate forced with -r */ int top_field_first; int guess_layout_max; int autorotate; - int resample_height; - int resample_width; - int resample_pix_fmt; - - int resample_sample_fmt; - int resample_sample_rate; - int resample_channels; - uint64_t resample_channel_layout; int fix_sub_duration; struct { /* previous decoded subtitle and related variables */ @@ -309,6 +346,7 @@ typedef struct InputStream { struct sub2video { int64_t last_pts; int64_t end_pts; + AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init AVFrame *frame; int w, h; } sub2video; @@ -324,16 +362,18 @@ typedef struct InputStream { /* hwaccel options */ enum HWAccelID hwaccel_id; + enum AVHWDeviceType hwaccel_device_type; char *hwaccel_device; + enum AVPixelFormat hwaccel_output_format; /* hwaccel context */ - enum HWAccelID active_hwaccel_id; void *hwaccel_ctx; void (*hwaccel_uninit)(AVCodecContext *s); int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; enum AVPixelFormat hwaccel_retrieved_pix_fmt; + AVBufferRef *hw_frames_ctx; /* stats */ // combined size of all the packets read @@ -343,6 +383,11 @@ typedef struct InputStream { // number of frames/samples retrieved from the decoder uint64_t frames_decoded; uint64_t samples_decoded; + + int64_t *dts_buffer; + int nb_dts_buffer; + + int got_output; } InputStream; typedef struct InputFile { @@ -367,7 +412,7 @@ typedef struct InputFile { int rate_emu; int accurate_seek; -#if HAVE_PTHREADS +#if HAVE_THREADS AVThreadMessageQueue *in_thread_queue; pthread_t thread; /* thread reading from this file */ int non_blocking; /* reading packets from the thread should not block */ @@ -410,8 +455,15 @@ typedef struct OutputStream { int64_t first_pts; /* dts of the last packet sent to the muxer */ int64_t last_mux_dts; - AVBitStreamFilterContext *bitstream_filters; + // the timebase of the packets sent to the muxer + AVRational mux_timebase; + AVRational enc_timebase; + + int nb_bitstream_filters; + AVBSFContext **bsf_ctx; + AVCodecContext *enc_ctx; + AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */ AVCodec *enc; int64_t max_frames; AVFrame *filtered_frame; @@ -427,10 +479,12 @@ typedef struct OutputStream { int force_fps; int top_field_first; int rotate_overridden; + double rotate_override_value; AVRational frame_aspect_ratio; /* forced key frames */ + int64_t forced_kf_ref_pts; int64_t *forced_kf_pts; int forced_kf_count; int forced_kf_index; @@ -458,6 +512,14 @@ typedef struct OutputStream { OSTFinished finished; /* no more packets should be written for this stream */ int unavailable; /* true if the steram is unavailable (possibly temporarily) */ int stream_copy; + + // init_output_stream() has been called for this stream + // The encoder and the bitstream filters have been initialized and the stream + // parameters are set in the AVStream. + int initialized; + + int inputs_done; + const char *attachment_filename; int copy_initial_nonkeyframes; int copy_prior_start; @@ -465,8 +527,6 @@ typedef struct OutputStream { int keep_pix_fmt; - AVCodecParserContext *parser; - /* stats */ // combined size of all the packets written uint64_t data_size; @@ -479,6 +539,11 @@ typedef struct OutputStream { /* packet quality factor */ int quality; + int max_muxing_queue_size; + + /* the packets are buffered here until the muxer is ready to be initialized */ + AVFifoBuffer *muxing_queue; + /* packet picture type */ int pict_type; @@ -495,6 +560,8 @@ typedef struct OutputFile { uint64_t limit_filesize; /* filesize limit expressed in bytes */ int shortest; + + int header_written; } OutputFile; extern InputStream **input_streams; @@ -538,13 +605,21 @@ extern int stdin_interaction; extern int frame_bits_per_raw_sample; extern AVIOContext *progress_avio; extern float max_error_rate; -extern int vdpau_api_ver; extern char *videotoolbox_pixfmt; +extern int filter_nbthreads; +extern int filter_complex_nbthreads; +extern int vstats_version; + extern const AVIOInterruptCB int_cb; extern const OptionDef options[]; extern const HWAccel hwaccels[]; +extern AVBufferRef *hw_device_ctx; +#if CONFIG_QSV +extern char *qsv_device; +#endif +extern HWDevice *filter_hw_device; void term_init(void); @@ -565,19 +640,31 @@ void choose_sample_fmt(AVStream *st, AVCodec *codec); int configure_filtergraph(FilterGraph *fg); int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out); +void check_filter_outputs(void); int ist_in_filtergraph(FilterGraph *fg, InputStream *ist); -FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost); +int filtergraph_is_simple(FilterGraph *fg); +int init_simple_filtergraph(InputStream *ist, OutputStream *ost); int init_complex_filtergraph(FilterGraph *fg); +void sub2video_update(InputStream *ist, AVSubtitle *sub); + +int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); + int ffmpeg_parse_options(int argc, char **argv); -int vdpau_init(AVCodecContext *s); -int dxva2_init(AVCodecContext *s); -int vda_init(AVCodecContext *s); int videotoolbox_init(AVCodecContext *s); int qsv_init(AVCodecContext *s); -int qsv_transcode_init(OutputStream *ost); +int cuvid_init(AVCodecContext *s); + +HWDevice *hw_device_get_by_name(const char *name); +int hw_device_init_from_string(const char *arg, HWDevice **dev); +void hw_device_free_all(void); + +int hw_device_setup_for_decode(InputStream *ist); +int hw_device_setup_for_encode(OutputStream *ost); + +int hwaccel_decode_init(AVCodecContext *avctx); int run(int argc, char **argv); -#endif /* FFMPEG_H */ +#endif /* FFTOOLS_FFMPEG_H */ diff --git a/app/src/main/cpp/ffmpeg/ffmpeg_filter.c b/app/src/main/cpp/ffmpeg/ffmpeg_filter.c index 733d30e..c79c158 100644 --- a/app/src/main/cpp/ffmpeg/ffmpeg_filter.c +++ b/app/src/main/cpp/ffmpeg/ffmpeg_filter.c @@ -20,10 +20,11 @@ #include -#include "ffmpeg/ffmpeg.h" +#include "ffmpeg.h" #include "libavfilter/avfilter.h" #include "libavfilter/buffersink.h" +#include "libavfilter/buffersrc.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -36,7 +37,6 @@ #include "libavutil/imgutils.h" #include "libavutil/samplefmt.h" - static const enum AVPixelFormat *get_compliance_unofficial_pix_fmts(enum AVCodecID codec_id, const enum AVPixelFormat default_formats[]) { static const enum AVPixelFormat mjpeg_formats[] = @@ -63,6 +63,7 @@ enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, AVCod if (codec && codec->pix_fmts) { const enum AVPixelFormat *p = codec->pix_fmts; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); + //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; enum AVPixelFormat best= AV_PIX_FMT_NONE; @@ -92,33 +93,33 @@ void choose_sample_fmt(AVStream *st, AVCodec *codec) if (codec && codec->sample_fmts) { const enum AVSampleFormat *p = codec->sample_fmts; for (; *p != -1; p++) { - if (*p == st->codec->sample_fmt) + if (*p == st->codecpar->format) break; } if (*p == -1) { - if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0])) + if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codecpar->format) > av_get_sample_fmt_name(codec->sample_fmts[0])) av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n"); - if(av_get_sample_fmt_name(st->codec->sample_fmt)) + if(av_get_sample_fmt_name(st->codecpar->format)) av_log(NULL, AV_LOG_WARNING, "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n", - av_get_sample_fmt_name(st->codec->sample_fmt), + av_get_sample_fmt_name(st->codecpar->format), codec->name, av_get_sample_fmt_name(codec->sample_fmts[0])); - st->codec->sample_fmt = codec->sample_fmts[0]; + st->codecpar->format = codec->sample_fmts[0]; } } } -static char *choose_pix_fmts(OutputStream *ost) +static char *choose_pix_fmts(OutputFilter *ofilter) { + OutputStream *ost = ofilter->ost; AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); if (strict_dict) // used by choose_pixel_fmt() and below av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); if (ost->keep_pix_fmt) { - if (ost->filter) - avfilter_graph_set_auto_convert(ost->filter->graph->graph, + avfilter_graph_set_auto_convert(ofilter->graph->graph, AVFILTER_AUTO_CONVERT_NONE); if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) return NULL; @@ -153,13 +154,13 @@ static char *choose_pix_fmts(OutputStream *ost) /* Define a function for building a string containing a list of * allowed formats. */ -#define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name) \ -static char *choose_ ## var ## s(OutputStream *ost) \ +#define DEF_CHOOSE_FORMAT(suffix, type, var, supported_list, none, get_name) \ +static char *choose_ ## suffix (OutputFilter *ofilter) \ { \ - if (ost->enc_ctx->var != none) { \ - get_name(ost->enc_ctx->var); \ + if (ofilter->var != none) { \ + get_name(ofilter->var); \ return av_strdup(name); \ - } else if (ost->enc && ost->enc->supported_list) { \ + } else if (ofilter->supported_list) { \ const type *p; \ AVIOContext *s = NULL; \ uint8_t *ret; \ @@ -168,7 +169,7 @@ static char *choose_ ## var ## s(OutputStream *ost) \ if (avio_open_dyn_buf(&s) < 0) \ exit_program(1); \ \ - for (p = ost->enc->supported_list; *p != none; p++) { \ + for (p = ofilter->supported_list; *p != none; p++) { \ get_name(*p); \ avio_printf(s, "%s|", name); \ } \ @@ -179,19 +180,19 @@ static char *choose_ ## var ## s(OutputStream *ost) \ return NULL; \ } -// DEF_CHOOSE_FORMAT(enum AVPixelFormat, pix_fmt, pix_fmts, AV_PIX_FMT_NONE, -// GET_PIX_FMT_NAME) +//DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats, AV_PIX_FMT_NONE, +// GET_PIX_FMT_NAME) -DEF_CHOOSE_FORMAT(enum AVSampleFormat, sample_fmt, sample_fmts, +DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats, AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME) -DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0, +DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, GET_SAMPLE_RATE_NAME) -DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0, +DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0, GET_CH_LAYOUT_NAME) -FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) +int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { FilterGraph *fg = av_mallocz(sizeof(*fg)); @@ -204,6 +205,7 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) exit_program(1); fg->outputs[0]->ost = ost; fg->outputs[0]->graph = fg; + fg->outputs[0]->format = -1; ost->filter = fg->outputs[0]; @@ -212,6 +214,11 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) exit_program(1); fg->inputs[0]->ist = ist; fg->inputs[0]->graph = fg; + fg->inputs[0]->format = -1; + + fg->inputs[0]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!fg->inputs[0]->frame_queue) + exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = fg->inputs[0]; @@ -219,7 +226,26 @@ FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) GROW_ARRAY(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1] = fg; - return fg; + return 0; +} + +static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) +{ + AVFilterContext *ctx = inout->filter_ctx; + AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; + int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; + AVIOContext *pb; + uint8_t *res = NULL; + + if (avio_open_dyn_buf(&pb) < 0) + exit_program(1); + + avio_printf(pb, "%s", ctx->filter->name); + if (nb_pads > 1) + avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx)); + avio_w8(pb, 0); + avio_close_dyn_buf(pb, &res); + return res; } static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) @@ -249,7 +275,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) s = input_files[file_idx]->ctx; for (i = 0; i < s->nb_streams; i++) { - enum AVMediaType stream_type = s->streams[i]->codec->codec_type; + enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type; if (stream_type != type && !(stream_type == AVMEDIA_TYPE_SUBTITLE && type == AVMEDIA_TYPE_VIDEO /* sub2video hack */)) @@ -265,10 +291,17 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) exit_program(1); } ist = input_streams[input_files[file_idx]->ist_index + st->index]; + if (ist->user_set_discard == AVDISCARD_ALL) { + av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " + "matches a disabled input stream.\n", p, fg->graph_desc); + exit_program(1); + } } else { /* find the first unused stream of corresponding type */ for (i = 0; i < nb_input_streams; i++) { ist = input_streams[i]; + if (ist->user_set_discard == AVDISCARD_ALL) + continue; if (ist->dec_ctx->codec_type == type && ist->discard) break; } @@ -290,6 +323,13 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) exit_program(1); fg->inputs[fg->nb_inputs - 1]->ist = ist; fg->inputs[fg->nb_inputs - 1]->graph = fg; + fg->inputs[fg->nb_inputs - 1]->format = -1; + fg->inputs[fg->nb_inputs - 1]->type = ist->st->codecpar->codec_type; + fg->inputs[fg->nb_inputs - 1]->name = describe_filter_link(fg, in, 1); + + fg->inputs[fg->nb_inputs - 1]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!fg->inputs[fg->nb_inputs - 1]->frame_queue) + exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; @@ -306,6 +346,7 @@ int init_complex_filtergraph(FilterGraph *fg) graph = avfilter_graph_alloc(); if (!graph) return AVERROR(ENOMEM); + graph->nb_threads = 1; ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs); if (ret < 0) @@ -324,6 +365,7 @@ int init_complex_filtergraph(FilterGraph *fg) fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; fg->outputs[fg->nb_outputs - 1]->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); + fg->outputs[fg->nb_outputs - 1]->name = describe_filter_link(fg, cur, 0); cur = cur->next; fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; } @@ -412,13 +454,12 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; int ret; char name[255]; - snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); + snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("buffersink"), name, NULL, NULL, fg->graph); @@ -426,21 +467,20 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, if (ret < 0) return ret; - if (codec->width || codec->height) { + if (ofilter->width || ofilter->height) { char args[255]; AVFilterContext *filter; AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "%d:%d", - codec->width, - codec->height); + ofilter->width, ofilter->height); while ((e = av_dict_get(ost->sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); } - snprintf(name, sizeof(name), "scaler for output stream %d:%d", + snprintf(name, sizeof(name), "scaler_out_%d_%d", ost->file_index, ost->index); if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), name, args, NULL, fg->graph)) < 0) @@ -452,9 +492,9 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if ((pix_fmts = choose_pix_fmts(ost))) { + if ((pix_fmts = choose_pix_fmts(ofilter))) { AVFilterContext *filter; - snprintf(name, sizeof(name), "pixel format for output stream %d:%d", + snprintf(name, sizeof(name), "format_out_%d_%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("format"), @@ -475,7 +515,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num, ost->frame_rate.den); - snprintf(name, sizeof(name), "fps for output stream %d:%d", + snprintf(name, sizeof(name), "fps_out_%d_%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"), name, args, NULL, fg->graph); @@ -489,7 +529,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - snprintf(name, sizeof(name), "trim for output stream %d:%d", + snprintf(name, sizeof(name), "trim_out_%d_%d", ost->file_index, ost->index); ret = insert_trim(of->start_time, of->recording_time, &last_filter, &pad_idx, name); @@ -514,7 +554,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, char name[255]; int ret; - snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); + snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("abuffersink"), name, NULL, NULL, fg->graph); @@ -559,9 +599,9 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, if (codec->channels && !codec->channel_layout) codec->channel_layout = av_get_default_channel_layout(codec->channels); - sample_fmts = choose_sample_fmts(ost); - sample_rates = choose_sample_rates(ost); - channel_layouts = choose_channel_layouts(ost); + sample_fmts = choose_sample_fmts(ofilter); + sample_rates = choose_sample_rates(ofilter); + channel_layouts = choose_channel_layouts(ofilter); if (sample_fmts || sample_rates || channel_layouts) { AVFilterContext *format; char args[256]; @@ -581,7 +621,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, av_freep(&sample_rates); av_freep(&channel_layouts); - snprintf(name, sizeof(name), "audio format for output stream %d:%d", + snprintf(name, sizeof(name), "format_out_%d_%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&format, avfilter_get_by_name("aformat"), @@ -609,7 +649,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, int i; for (i=0; ictx->nb_streams; i++) - if (of->ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (of->ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) break; if (ictx->nb_streams) { @@ -631,30 +671,10 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, return 0; } -#define DESCRIBE_FILTER_LINK(f, inout, in) \ -{ \ - AVFilterContext *ctx = inout->filter_ctx; \ - AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \ - int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; \ - AVIOContext *pb; \ - \ - if (avio_open_dyn_buf(&pb) < 0) \ - exit_program(1); \ - \ - avio_printf(pb, "%s", ctx->filter->name); \ - if (nb_pads > 1) \ - avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\ - avio_w8(pb, 0); \ - avio_close_dyn_buf(pb, &f->name); \ -} - int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { - av_freep(&ofilter->name); - DESCRIBE_FILTER_LINK(ofilter, out, 0); - if (!ofilter->ost) { - av_log(NULL, AV_LOG_FATAL, "Filter %s has a unconnected output\n", ofilter->name); + av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name); exit_program(1); } @@ -665,21 +685,36 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu } } -static int sub2video_prepare(InputStream *ist) +void check_filter_outputs(void) +{ + int i; + for (i = 0; i < nb_filtergraphs; i++) { + int n; + for (n = 0; n < filtergraphs[i]->nb_outputs; n++) { + OutputFilter *output = filtergraphs[i]->outputs[n]; + if (!output->ost) { + av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", output->name); + exit_program(1); + } + } + } +} + +static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) { AVFormatContext *avf = input_files[ist->file_index]->ctx; int i, w, h; /* Compute the size of the canvas for the subtitles stream. - If the subtitles codec has set a size, use it. Otherwise use the + If the subtitles codecpar has set a size, use it. Otherwise use the maximum dimensions of the video streams in the same file. */ - w = ist->dec_ctx->width; - h = ist->dec_ctx->height; + w = ifilter->width; + h = ifilter->height; if (!(w && h)) { for (i = 0; i < avf->nb_streams; i++) { - if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - w = FFMAX(w, avf->streams[i]->codec->width); - h = FFMAX(h, avf->streams[i]->codec->height); + if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + w = FFMAX(w, avf->streams[i]->codecpar->width); + h = FFMAX(h, avf->streams[i]->codecpar->height); } } if (!(w && h)) { @@ -688,17 +723,21 @@ static int sub2video_prepare(InputStream *ist) } av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); } - ist->sub2video.w = ist->resample_width = w; - ist->sub2video.h = ist->resample_height = h; + ist->sub2video.w = ifilter->width = w; + ist->sub2video.h = ifilter->height = h; + + ifilter->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; + ifilter->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the palettes for all rectangles are identical or compatible */ - ist->resample_pix_fmt = ist->dec_ctx->pix_fmt = AV_PIX_FMT_RGB32; + ifilter->format = AV_PIX_FMT_RGB32; ist->sub2video.frame = av_frame_alloc(); if (!ist->sub2video.frame) return AVERROR(ENOMEM); ist->sub2video.last_pts = INT64_MIN; + ist->sub2video.end_pts = INT64_MIN; return 0; } @@ -717,32 +756,36 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, char name[255]; int ret, pad_idx = 0; int64_t tsoffset = 0; + AVBufferSrcParameters *par = av_buffersrc_parameters_alloc(); + + if (!par) + return AVERROR(ENOMEM); + memset(par, 0, sizeof(*par)); + par->format = AV_PIX_FMT_NONE; if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } if (!fr.num) fr = av_guess_frame_rate(input_files[ist->file_index]->ctx, ist->st, NULL); if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { - ret = sub2video_prepare(ist); + ret = sub2video_prepare(ist, ifilter); if (ret < 0) - return ret; + goto fail; } - sar = ist->st->sample_aspect_ratio.num ? - ist->st->sample_aspect_ratio : - ist->dec_ctx->sample_aspect_ratio; + sar = ifilter->sample_aspect_ratio; if(!sar.den) sar = (AVRational){0,1}; - av_bprint_init(&args, 0, 1); + av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" - "pixel_aspect=%d/%d:sws_param=flags=%d", ist->resample_width, - ist->resample_height, - ist->hwaccel_retrieve_data ? ist->hwaccel_retrieved_pix_fmt : ist->resample_pix_fmt, + "pixel_aspect=%d/%d:sws_param=flags=%d", + ifilter->width, ifilter->height, ifilter->format, tb.num, tb.den, sar.num, sar.den, SWS_BILINEAR + ((ist->dec_ctx->flags&AV_CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); if (fr.num && fr.den) @@ -750,9 +793,15 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, ist->file_index, ist->st->index); + if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, args.str, NULL, fg->graph)) < 0) - return ret; + goto fail; + par->hw_frames_ctx = ifilter->hw_frames_ctx; + ret = av_buffersrc_parameters_set(ifilter->filter, par); + if (ret < 0) + goto fail; + av_freep(&par); last_filter = ifilter->filter; if (ist->autorotate) { @@ -776,27 +825,10 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, return ret; } - if (ist->framerate.num) { - AVFilterContext *setpts; - - snprintf(name, sizeof(name), "force CFR for input from stream %d:%d", - ist->file_index, ist->st->index); - if ((ret = avfilter_graph_create_filter(&setpts, - avfilter_get_by_name("setpts"), - name, "N", NULL, - fg->graph)) < 0) - return ret; - - if ((ret = avfilter_link(last_filter, 0, setpts, 0)) < 0) - return ret; - - last_filter = setpts; - } - if (do_deinterlace) { AVFilterContext *yadif; - snprintf(name, sizeof(name), "deinterlace input from stream %d:%d", + snprintf(name, sizeof(name), "deinterlace_in_%d_%d", ist->file_index, ist->st->index); if ((ret = avfilter_graph_create_filter(&yadif, avfilter_get_by_name("yadif"), @@ -810,7 +842,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, last_filter = yadif; } - snprintf(name, sizeof(name), "trim for input stream %d:%d", + snprintf(name, sizeof(name), "trim_in_%d_%d", ist->file_index, ist->st->index); if (copy_ts) { tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time; @@ -826,6 +858,10 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) return ret; return 0; +fail: + av_freep(&par); + + return ret; } static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, @@ -847,15 +883,15 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", - 1, ist->dec_ctx->sample_rate, - ist->dec_ctx->sample_rate, - av_get_sample_fmt_name(ist->dec_ctx->sample_fmt)); - if (ist->dec_ctx->channel_layout) + 1, ifilter->sample_rate, + ifilter->sample_rate, + av_get_sample_fmt_name(ifilter->format)); + if (ifilter->channel_layout) av_bprintf(&args, ":channel_layout=0x%"PRIx64, - ist->dec_ctx->channel_layout); + ifilter->channel_layout); else - av_bprintf(&args, ":channels=%d", ist->dec_ctx->channels); - snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, + av_bprintf(&args, ":channels=%d", ifilter->channels); + snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index, ist->file_index, ist->st->index); if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt, @@ -870,7 +906,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ "similarly to -af " filter_name "=%s.\n", arg); \ \ - snprintf(name, sizeof(name), "graph %d %s for input stream %d:%d", \ + snprintf(name, sizeof(name), "graph_%d_%s_in_%d_%d", \ fg->index, filter_name, ist->file_index, ist->st->index); \ ret = avfilter_graph_create_filter(&filt_ctx, \ avfilter_get_by_name(filter_name), \ @@ -941,9 +977,6 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { - av_freep(&ifilter->name); - DESCRIBE_FILTER_LINK(ifilter, in, 1); - if (!ifilter->ist->dec) { av_log(NULL, AV_LOG_ERROR, "No decoder for stream #%d:%d, filtering impossible\n", @@ -957,14 +990,24 @@ static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, } } +static void cleanup_filtergraph(FilterGraph *fg) +{ + int i; + for (i = 0; i < fg->nb_outputs; i++) + fg->outputs[i]->filter = (AVFilterContext *)NULL; + for (i = 0; i < fg->nb_inputs; i++) + fg->inputs[i]->filter = (AVFilterContext *)NULL; + avfilter_graph_free(&fg->graph); +} + int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; - int ret, i, simple = !fg->graph_desc; + int ret, i, simple = filtergraph_is_simple(fg); const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; - avfilter_graph_free(&fg->graph); + cleanup_filtergraph(fg); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); @@ -973,6 +1016,8 @@ int configure_filtergraph(FilterGraph *fg) char args[512]; AVDictionaryEntry *e = NULL; + fg->graph->nb_threads = filter_nbthreads; + args[0] = 0; while ((e = av_dict_get(ost->sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { @@ -998,15 +1043,28 @@ int configure_filtergraph(FilterGraph *fg) } if (strlen(args)) args[strlen(args) - 1] = '\0'; - fg->graph->resample_lavr_opts = av_strdup(args); e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); if (e) av_opt_set(fg->graph, "threads", e->value, 0); + } else { + fg->graph->nb_threads = filter_complex_nbthreads; } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) - return ret; + goto fail; + + if (filter_hw_device || hw_device_ctx) { + AVBufferRef *device = filter_hw_device ? filter_hw_device->device_ref + : hw_device_ctx; + for (i = 0; i < fg->graph->nb_filters; i++) { + fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(device); + if (!fg->graph->filters[i]->hw_device_ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + } if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { const char *num_inputs; @@ -1030,14 +1088,15 @@ int configure_filtergraph(FilterGraph *fg) " However, it had %s input(s) and %s output(s)." " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n", graph_desc, num_inputs, num_outputs); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); - return ret; + goto fail; } avfilter_inout_free(&inputs); @@ -1046,7 +1105,22 @@ int configure_filtergraph(FilterGraph *fg) avfilter_inout_free(&outputs); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) - return ret; + goto fail; + + /* limit the lists of allowed formats to the ones selected, to + * make sure they stay the same if the filtergraph is reconfigured later */ + for (i = 0; i < fg->nb_outputs; i++) { + OutputFilter *ofilter = fg->outputs[i]; + AVFilterContext *sink = ofilter->filter; + + ofilter->format = av_buffersink_get_format(sink); + + ofilter->width = av_buffersink_get_w(sink); + ofilter->height = av_buffersink_get_h(sink); + + ofilter->sample_rate = av_buffersink_get_sample_rate(sink); + ofilter->channel_layout = av_buffersink_get_channel_layout(sink); + } fg->reconfiguration = 1; @@ -1056,8 +1130,9 @@ int configure_filtergraph(FilterGraph *fg) /* identical to the same check in ffmpeg.c, needed because complex filter graphs are initialized earlier */ av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n", - avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); - return AVERROR(EINVAL); + avcodec_get_name(ost->st->codecpar->codec_id), ost->file_index, ost->index); + ret = AVERROR(EINVAL); + goto fail; } if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) @@ -1065,6 +1140,66 @@ int configure_filtergraph(FilterGraph *fg) ost->enc_ctx->frame_size); } + for (i = 0; i < fg->nb_inputs; i++) { + while (av_fifo_size(fg->inputs[i]->frame_queue)) { + AVFrame *tmp; + av_fifo_generic_read(fg->inputs[i]->frame_queue, &tmp, sizeof(tmp), NULL); + ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp); + av_frame_free(&tmp); + if (ret < 0) + goto fail; + } + } + + /* send the EOFs for the finished inputs */ + for (i = 0; i < fg->nb_inputs; i++) { + if (fg->inputs[i]->eof) { + ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL); + if (ret < 0) + goto fail; + } + } + + /* process queued up subtitle packets */ + for (i = 0; i < fg->nb_inputs; i++) { + InputStream *ist = fg->inputs[i]->ist; + if (ist->sub2video.sub_queue && ist->sub2video.frame) { + while (av_fifo_size(ist->sub2video.sub_queue)) { + AVSubtitle tmp; + av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL); + sub2video_update(ist, &tmp); + avsubtitle_free(&tmp); + } + } + } + + return 0; + +fail: + cleanup_filtergraph(fg); + return ret; +} + +int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) +{ + av_buffer_unref(&ifilter->hw_frames_ctx); + + ifilter->format = frame->format; + + ifilter->width = frame->width; + ifilter->height = frame->height; + ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; + + ifilter->sample_rate = frame->sample_rate; + ifilter->channels = frame->channels; + ifilter->channel_layout = frame->channel_layout; + + if (frame->hw_frames_ctx) { + ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); + if (!ifilter->hw_frames_ctx) + return AVERROR(ENOMEM); + } + return 0; } @@ -1077,3 +1212,7 @@ int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) return 0; } +int filtergraph_is_simple(FilterGraph *fg) +{ + return !fg->graph_desc; +} diff --git a/app/src/main/cpp/ffmpeg/ffmpeg_opt.c b/app/src/main/cpp/ffmpeg/ffmpeg_opt.c index bb15439..f5ca18a 100644 --- a/app/src/main/cpp/ffmpeg/ffmpeg_opt.c +++ b/app/src/main/cpp/ffmpeg/ffmpeg_opt.c @@ -20,8 +20,8 @@ #include -#include "ffmpeg/ffmpeg.h" -#include "ffmpeg/cmdutils.h" +#include "ffmpeg.h" +#include "cmdutils.h" #include "libavformat/avformat.h" @@ -40,7 +40,6 @@ #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" -#include "libavutil/time_internal.h" #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" @@ -67,23 +66,19 @@ } const HWAccel hwaccels[] = { -#if HAVE_VDPAU_X11 - { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU }, -#endif -#if HAVE_DXVA2_LIB - { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD }, -#endif -#if CONFIG_VDA - { "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, -#endif #if CONFIG_VIDEOTOOLBOX - { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, + { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, #endif #if CONFIG_LIBMFX { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, +#endif +#if CONFIG_CUVID + { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA }, #endif { 0 }, }; +AVBufferRef *hw_device_ctx; +HWDevice *filter_hw_device; char *vstats_filename; char *sdp_filename; @@ -112,6 +107,9 @@ int qp_hist = 0; int stdin_interaction = 1; int frame_bits_per_raw_sample = 0; float max_error_rate = 2.0/3; +int filter_nbthreads = 0; +int filter_complex_nbthreads = 0; +int vstats_version = 2; static int intra_only = 0; @@ -119,10 +117,10 @@ static int file_overwrite = 0; static int no_file_overwrite = 0; static int do_psnr = 0; static int input_sync; -static int override_ffserver = 0; static int input_stream_potentially_available = 0; static int ignore_unknown_streams = 0; static int copy_unknown_streams = 0; +static int find_stream_info = 1; static void uninit_options(OptionsContext *o) { @@ -172,12 +170,15 @@ static void init_options(OptionsContext *o) static int show_hwaccels(void *optctx, const char *opt, const char *arg) { + enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE; int i; printf("Hardware acceleration methods:\n"); - for (i = 0; i < FF_ARRAY_ELEMS(hwaccels) - 1; i++) { + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + printf("%s\n", av_hwdevice_get_type_name(type)); + for (i = 0; hwaccels[i].name; i++) printf("%s\n", hwaccels[i].name); - } printf("\n"); return 0; } @@ -267,7 +268,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; StreamMap *m = NULL; - int i, negative = 0, file_idx; + int i, negative = 0, file_idx, disabled = 0; int sync_file_idx = -1, sync_stream_idx = 0; char *p, *sync; char *map; @@ -302,6 +303,11 @@ static int opt_map(void *optctx, const char *opt, const char *arg) "match any streams.\n", arg); exit_program(1); } + if (input_streams[input_files[sync_file_idx]->ist_index + sync_stream_idx]->user_set_discard == AVDISCARD_ALL) { + av_log(NULL, AV_LOG_FATAL, "Sync stream specification in map %s matches a disabled input " + "stream.\n", arg); + exit_program(1); + } } @@ -338,6 +344,10 @@ static int opt_map(void *optctx, const char *opt, const char *arg) if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i], *p == ':' ? p + 1 : p) <= 0) continue; + if (input_streams[input_files[file_idx]->ist_index + i]->user_set_discard == AVDISCARD_ALL) { + disabled = 1; + continue; + } GROW_ARRAY(o->stream_maps, o->nb_stream_maps); m = &o->stream_maps[o->nb_stream_maps - 1]; @@ -357,6 +367,10 @@ static int opt_map(void *optctx, const char *opt, const char *arg) if (!m) { if (allow_unused) { av_log(NULL, AV_LOG_VERBOSE, "Stream map '%s' matches no streams; ignoring.\n", arg); + } else if (disabled) { + av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches disabled streams.\n" + "To ignore this, add a trailing '?' to the map.\n", arg); + exit_program(1); } else { av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n" "To ignore this, add a trailing '?' to the map.\n", arg); @@ -382,6 +396,11 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) int n; AVStream *st; AudioChannelMap *m; + char *allow_unused; + char *mapchan; + mapchan = av_strdup(arg); + if (!mapchan) + return AVERROR(ENOMEM); GROW_ARRAY(o->audio_channel_maps, o->nb_audio_channel_maps); m = &o->audio_channel_maps[o->nb_audio_channel_maps - 1]; @@ -392,6 +411,7 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) m->file_idx = m->stream_idx = -1; if (n == 1) m->ofile_idx = m->ostream_idx = -1; + av_free(mapchan); return 0; } @@ -422,16 +442,28 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) exit_program(1); } st = input_files[m->file_idx]->ctx->streams[m->stream_idx]; - if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n", m->file_idx, m->stream_idx); exit_program(1); } - if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) { - av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n", - m->file_idx, m->stream_idx, m->channel_idx); - exit_program(1); + /* allow trailing ? to map_channel */ + if (allow_unused = strchr(mapchan, '?')) + *allow_unused = 0; + if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels || + input_streams[input_files[m->file_idx]->ist_index + m->stream_idx]->user_set_discard == AVDISCARD_ALL) { + if (allow_unused) { + av_log(NULL, AV_LOG_VERBOSE, "mapchan: invalid audio channel #%d.%d.%d\n", + m->file_idx, m->stream_idx, m->channel_idx); + } else { + av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n" + "To ignore this, add a trailing '?' to the map_channel.\n", + m->file_idx, m->stream_idx, m->channel_idx); + exit_program(1); + } + } + av_free(mapchan); return 0; } @@ -442,6 +474,56 @@ static int opt_sdp_file(void *optctx, const char *opt, const char *arg) return 0; } +#if CONFIG_VAAPI +static int opt_vaapi_device(void *optctx, const char *opt, const char *arg) +{ + HWDevice *dev; + const char *prefix = "vaapi:"; + char *tmp; + int err; + tmp = av_asprintf("%s%s", prefix, arg); + if (!tmp) + return AVERROR(ENOMEM); + err = hw_device_init_from_string(tmp, &dev); + av_free(tmp); + if (err < 0) + return err; + hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!hw_device_ctx) + return AVERROR(ENOMEM); + return 0; +} +#endif + +static int opt_init_hw_device(void *optctx, const char *opt, const char *arg) +{ + if (!strcmp(arg, "list")) { + enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE; + printf("Supported hardware device types:\n"); + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + printf("%s\n", av_hwdevice_get_type_name(type)); + printf("\n"); + exit_program(0); + } else { + return hw_device_init_from_string(arg, NULL); + } +} + +static int opt_filter_hw_device(void *optctx, const char *opt, const char *arg) +{ + if (filter_hw_device) { + av_log(NULL, AV_LOG_ERROR, "Only one filter device can be used.\n"); + return AVERROR(EINVAL); + } + filter_hw_device = hw_device_get_by_name(arg); + if (!filter_hw_device) { + av_log(NULL, AV_LOG_ERROR, "Invalid filter device %s.\n", arg); + return AVERROR(EINVAL); + } + return 0; +} + /** * Parse a metadata specifier passed as 'arg' parameter. * @param arg metadata string to parse @@ -616,11 +698,11 @@ static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream * MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st); if (codec_name) { - AVCodec *codec = find_codec_or_die(codec_name, st->codec->codec_type, 0); - st->codec->codec_id = codec->id; + AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); + st->codecpar->codec_id = codec->id; return codec; } else - return avcodec_find_decoder(st->codec->codec_id); + return avcodec_find_decoder(st->codecpar->codec_id); } /* Add all the streams from the given input file to the global @@ -631,13 +713,16 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; - AVCodecContext *dec = st->codec; + AVCodecParameters *par = st->codecpar; InputStream *ist = av_mallocz(sizeof(*ist)); - char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL; + char *framerate = NULL, *hwaccel_device = NULL; + const char *hwaccel = NULL; + char *hwaccel_output_format = NULL; char *codec_tag = NULL; char *next; char *discard_str = NULL; - const AVOption *discard_opt = av_opt_find(dec, "skip_frame", NULL, 0, 0); + const AVClass *cc = avcodec_get_class(); + const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, 0); if (!ist) exit_program(1); @@ -664,18 +749,25 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) uint32_t tag = strtol(codec_tag, &next, 0); if (*next) tag = AV_RL32(codec_tag); - st->codec->codec_tag = tag; + st->codecpar->codec_tag = tag; } ist->dec = choose_decoder(o, ic, st); - ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, ist->dec); + ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec); ist->reinit_filters = -1; MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st); MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st); ist->user_set_discard = AVDISCARD_NONE; - if (discard_str && av_opt_eval_int(dec, discard_opt, discard_str, &ist->user_set_discard) < 0) { + + if ((o->video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) || + (o->audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) || + (o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) || + (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)) + ist->user_set_discard = AVDISCARD_ALL; + + if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) { av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n", discard_str); exit_program(1); @@ -689,25 +781,31 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) exit_program(1); } - ret = avcodec_copy_context(ist->dec_ctx, dec); + ret = avcodec_parameters_to_context(ist->dec_ctx, par); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n"); exit_program(1); } - switch (dec->codec_type) { + if (o->bitexact) + ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: if(!ist->dec) - ist->dec = avcodec_find_decoder(dec->codec_id); -#if FF_API_EMU_EDGE - if (av_codec_get_lowres(dec)) { - dec->flags |= CODEC_FLAG_EMU_EDGE; + ist->dec = avcodec_find_decoder(par->codec_id); +#if FF_API_LOWRES + if (st->codec->lowres) { + ist->dec_ctx->lowres = st->codec->lowres; + ist->dec_ctx->width = st->codec->width; + ist->dec_ctx->height = st->codec->height; + ist->dec_ctx->coded_width = st->codec->coded_width; + ist->dec_ctx->coded_height = st->codec->coded_height; } #endif - ist->resample_height = ist->dec_ctx->height; - ist->resample_width = ist->dec_ctx->width; - ist->resample_pix_fmt = ist->dec_ctx->pix_fmt; + // avformat_find_stream_info() doesn't set this for us anymore. + ist->dec_ctx->framerate = st->avg_frame_rate; MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); if (framerate && av_parse_video_rate(&ist->framerate, @@ -722,11 +820,16 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); if (hwaccel) { + // The NVDEC hwaccels use a CUDA device, so remap the name here. + if (!strcmp(hwaccel, "nvdec")) + hwaccel = "cuda"; + if (!strcmp(hwaccel, "none")) ist->hwaccel_id = HWACCEL_NONE; else if (!strcmp(hwaccel, "auto")) ist->hwaccel_id = HWACCEL_AUTO; else { + enum AVHWDeviceType type; int i; for (i = 0; hwaccels[i].name; i++) { if (!strcmp(hwaccels[i].name, hwaccel)) { @@ -735,10 +838,23 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } } + if (!ist->hwaccel_id) { + type = av_hwdevice_find_type_by_name(hwaccel); + if (type != AV_HWDEVICE_TYPE_NONE) { + ist->hwaccel_id = HWACCEL_GENERIC; + ist->hwaccel_device_type = type; + } + } + if (!ist->hwaccel_id) { av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", hwaccel); av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: "); + type = AV_HWDEVICE_TYPE_NONE; + while ((type = av_hwdevice_iterate_types(type)) != + AV_HWDEVICE_TYPE_NONE) + av_log(NULL, AV_LOG_FATAL, "%s ", + av_hwdevice_get_type_name(type)); for (i = 0; hwaccels[i].name; i++) av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name); av_log(NULL, AV_LOG_FATAL, "\n"); @@ -753,6 +869,19 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) if (!ist->hwaccel_device) exit_program(1); } + + MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, + hwaccel_output_format, ic, st); + if (hwaccel_output_format) { + ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); + if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { + av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output " + "format: %s", hwaccel_output_format); + } + } else { + ist->hwaccel_output_format = AV_PIX_FMT_NONE; + } + ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; break; @@ -760,18 +889,12 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->guess_layout_max = INT_MAX; MATCH_PER_STREAM_OPT(guess_layout_max, i, ist->guess_layout_max, ic, st); guess_input_channel_layout(ist); - - ist->resample_sample_fmt = ist->dec_ctx->sample_fmt; - ist->resample_sample_rate = ist->dec_ctx->sample_rate; - ist->resample_channels = ist->dec_ctx->channels; - ist->resample_channel_layout = ist->dec_ctx->channel_layout; - break; case AVMEDIA_TYPE_DATA: case AVMEDIA_TYPE_SUBTITLE: { char *canvas_size = NULL; if(!ist->dec) - ist->dec = avcodec_find_decoder(dec->codec_id); + ist->dec = avcodec_find_decoder(par->codec_id); MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st); MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st); if (canvas_size && @@ -787,18 +910,25 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) default: abort(); } + + ret = avcodec_parameters_from_context(par, ist->dec_ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n"); + exit_program(1); + } } } static void assert_file_overwrite(const char *filename) { + const char *proto_name = avio_find_protocol_name(filename); + if (file_overwrite && no_file_overwrite) { fprintf(stderr, "Error, both -y and -n supplied. Exiting.\n"); exit_program(1); } if (!file_overwrite) { - const char *proto_name = avio_find_protocol_name(filename); if (proto_name && !strcmp(proto_name, "file") && avio_check(filename, 0) == 0) { if (stdin_interaction && !no_file_overwrite) { fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); @@ -817,6 +947,19 @@ static void assert_file_overwrite(const char *filename) } } } + + if (proto_name && !strcmp(proto_name, "file")) { + for (int i = 0; i < nb_input_files; i++) { + InputFile *file = input_files[i]; + if (file->ctx->iformat->flags & AVFMT_NOFILE) + continue; + if (!strcmp(filename, file->ctx->url)) { + av_log(NULL, AV_LOG_FATAL, "Output %s same as Input #%d - exiting\n", filename, i); + av_log(NULL, AV_LOG_WARNING, "FFmpeg cannot edit existing files in-place.\n"); + exit_program(1); + } + } + } } static void dump_attachment(AVStream *st, const char *filename) @@ -825,7 +968,7 @@ static void dump_attachment(AVStream *st, const char *filename) AVIOContext *out = NULL; AVDictionaryEntry *e; - if (!st->codec->extradata_size) { + if (!st->codecpar->extradata_size) { av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n", nb_input_files - 1, st->index); return; @@ -846,7 +989,7 @@ static void dump_attachment(AVStream *st, const char *filename) exit_program(1); } - avio_write(out, st->codec->extradata, st->codec->extradata_size); + avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size); avio_flush(out); avio_close(out); } @@ -858,16 +1001,29 @@ static int open_input_file(OptionsContext *o, const char *filename) AVInputFormat *file_iformat = NULL; int err, i, ret; int64_t timestamp; - AVDictionary **opts; AVDictionary *unused_opts = NULL; AVDictionaryEntry *e = NULL; - int orig_nb_streams; // number of streams before avformat_find_stream_info char * video_codec_name = NULL; char * audio_codec_name = NULL; char *subtitle_codec_name = NULL; char * data_codec_name = NULL; int scan_all_pmts_set = 0; + if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { + o->stop_time = INT64_MAX; + av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + } + + if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) { + int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; + if (o->stop_time <= start_time) { + av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); + exit_program(1); + } else { + o->recording_time = o->stop_time - start_time; + } + } + if (o->format) { if (!(file_iformat = av_find_input_format(o->format))) { av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format); @@ -921,25 +1077,23 @@ static int open_input_file(OptionsContext *o, const char *filename) MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, ic, "s"); MATCH_PER_TYPE_OPT(codec_names, str, data_codec_name, ic, "d"); - ic->video_codec_id = video_codec_name ? - find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)->id : AV_CODEC_ID_NONE; - ic->audio_codec_id = audio_codec_name ? - find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)->id : AV_CODEC_ID_NONE; - ic->subtitle_codec_id= subtitle_codec_name ? - find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : AV_CODEC_ID_NONE; - ic->data_codec_id = data_codec_name ? - find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)->id : AV_CODEC_ID_NONE; - if (video_codec_name) - av_format_set_video_codec (ic, find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)); + ic->video_codec = find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0); if (audio_codec_name) - av_format_set_audio_codec (ic, find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)); + ic->audio_codec = find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0); if (subtitle_codec_name) - av_format_set_subtitle_codec(ic, find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)); + ic->subtitle_codec = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0); if (data_codec_name) - av_format_set_data_codec(ic, find_codec_or_die(data_codec_name, AVMEDIA_TYPE_DATA, 0)); + ic->data_codec = find_codec_or_die(data_codec_name , AVMEDIA_TYPE_DATA , 0); + + ic->video_codec_id = video_codec_name ? ic->video_codec->id : AV_CODEC_ID_NONE; + ic->audio_codec_id = audio_codec_name ? ic->audio_codec->id : AV_CODEC_ID_NONE; + ic->subtitle_codec_id = subtitle_codec_name ? ic->subtitle_codec->id : AV_CODEC_ID_NONE; + ic->data_codec_id = data_codec_name ? ic->data_codec->id : AV_CODEC_ID_NONE; ic->flags |= AVFMT_FLAG_NONBLOCK; + if (o->bitexact) + ic->flags |= AVFMT_FLAG_BITEXACT; ic->interrupt_callback = int_cb; if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { @@ -950,6 +1104,8 @@ static int open_input_file(OptionsContext *o, const char *filename) err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts); if (err < 0) { print_error(filename, err); + if (err == AVERROR_PROTOCOL_NOT_FOUND) + av_log(NULL, AV_LOG_ERROR, "Did you mean file:%s?\n", filename); exit_program(1); } if (scan_all_pmts_set) @@ -961,24 +1117,43 @@ static int open_input_file(OptionsContext *o, const char *filename) for (i = 0; i < ic->nb_streams; i++) choose_decoder(o, ic, ic->streams[i]); - /* Set AVCodecContext options for avformat_find_stream_info */ - opts = setup_find_stream_info_opts(ic, o->g->codec_opts); - orig_nb_streams = ic->nb_streams; + if (find_stream_info) { + AVDictionary **opts = setup_find_stream_info_opts(ic, o->g->codec_opts); + int orig_nb_streams = ic->nb_streams; - /* If not enough info to get the stream parameters, we decode the - first frames to get it. (used in mpeg case for example) */ - ret = avformat_find_stream_info(ic, opts); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename); - if (ic->nb_streams == 0) { - avformat_close_input(&ic); - exit_program(1); + /* If not enough info to get the stream parameters, we decode the + first frames to get it. (used in mpeg case for example) */ + ret = avformat_find_stream_info(ic, opts); + + for (i = 0; i < orig_nb_streams; i++) + av_dict_free(&opts[i]); + av_freep(&opts); + + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename); + if (ic->nb_streams == 0) { + avformat_close_input(&ic); + exit_program(1); + } } } + if (o->start_time != AV_NOPTS_VALUE && o->start_time_eof != AV_NOPTS_VALUE) { + av_log(NULL, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss for %s\n", filename); + o->start_time_eof = AV_NOPTS_VALUE; + } + if (o->start_time_eof != AV_NOPTS_VALUE) { - if (ic->duration>0) { + if (o->start_time_eof >= 0) { + av_log(NULL, AV_LOG_ERROR, "-sseof value must be negative; aborting\n"); + exit_program(1); + } + if (ic->duration > 0) { o->start_time = o->start_time_eof + ic->duration; + if (o->start_time < 0) { + av_log(NULL, AV_LOG_WARNING, "-sseof value seeks to before start of file %s; ignored\n", filename); + o->start_time = AV_NOPTS_VALUE; + } } else av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename); } @@ -994,9 +1169,11 @@ static int open_input_file(OptionsContext *o, const char *filename) if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) { int dts_heuristic = 0; for (i=0; inb_streams; i++) { - AVCodecContext *avctx = ic->streams[i]->codec; - if (avctx->has_b_frames) + const AVCodecParameters *par = ic->streams[i]->codecpar; + if (par->video_delay) { dts_heuristic = 1; + break; + } } if (dts_heuristic) { seek_timestamp -= 3*AV_TIME_BASE / 23; @@ -1033,7 +1210,7 @@ static int open_input_file(OptionsContext *o, const char *filename) f->loop = o->loop; f->duration = 0; f->time_base = (AVRational){ 1, 1 }; -#if HAVE_PTHREADS +#if HAVE_THREADS f->thread_queue_size = o->thread_queue_size > 0 ? o->thread_queue_size : 8; #endif @@ -1086,10 +1263,6 @@ static int open_input_file(OptionsContext *o, const char *filename) } } - for (i = 0; i < orig_nb_streams; i++) - av_dict_free(&opts[i]); - av_freep(&opts); - input_stream_potentially_available = 1; return 0; @@ -1140,21 +1313,39 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV return ret; } -static void choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost) +static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost) { + enum AVMediaType type = ost->st->codecpar->codec_type; char *codec_name = NULL; - MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); - if (!codec_name) { - ost->st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename, - NULL, ost->st->codec->codec_type); - ost->enc = avcodec_find_encoder(ost->st->codec->codec_id); - } else if (!strcmp(codec_name, "copy")) - ost->stream_copy = 1; - else { - ost->enc = find_codec_or_die(codec_name, ost->st->codec->codec_type, 1); - ost->st->codec->codec_id = ost->enc->id; + if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { + MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); + if (!codec_name) { + ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->url, + NULL, ost->st->codecpar->codec_type); + ost->enc = avcodec_find_encoder(ost->st->codecpar->codec_id); + if (!ost->enc) { + av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for " + "output stream #%d:%d. Default encoder for format %s (codec %s) is " + "probably disabled. Please choose an encoder manually.\n", + ost->file_index, ost->index, s->oformat->name, + avcodec_get_name(ost->st->codecpar->codec_id)); + return AVERROR_ENCODER_NOT_FOUND; + } + } else if (!strcmp(codec_name, "copy")) + ost->stream_copy = 1; + else { + ost->enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1); + ost->st->codecpar->codec_id = ost->enc->id; + } + ost->encoding_needed = !ost->stream_copy; + } else { + /* no encoding supported for other media types */ + ost->stream_copy = 1; + ost->encoding_needed = 0; } + + return 0; } static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index) @@ -1162,8 +1353,8 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e OutputStream *ost; AVStream *st = avformat_new_stream(oc, NULL); int idx = oc->nb_streams - 1, ret = 0; - char *bsf = NULL, *next, *codec_tag = NULL; - AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL; + const char *bsfs = NULL, *time_base = NULL; + char *next, *codec_tag = NULL; double qscale = -1; int i; @@ -1183,8 +1374,15 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->file_index = nb_output_files - 1; ost->index = idx; ost->st = st; - st->codec->codec_type = type; - choose_encoder(o, oc, ost); + ost->forced_kf_ref_pts = AV_NOPTS_VALUE; + st->codecpar->codec_type = type; + + ret = choose_encoder(o, oc, ost); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error selecting an encoder for stream " + "%d:%d\n", ost->file_index, ost->index); + exit_program(1); + } ost->enc_ctx = avcodec_alloc_context3(ost->enc); if (!ost->enc_ctx) { @@ -1193,6 +1391,12 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e } ost->enc_ctx->codec_type = type; + ost->ref_par = avcodec_parameters_alloc(); + if (!ost->ref_par) { + av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding parameters.\n"); + exit_program(1); + } + if (ost->enc) { AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; @@ -1227,6 +1431,32 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } + + if (o->bitexact) + ost->enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + + MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + st->time_base = q; + } + + MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + ost->enc_timebase = q; + } + ost->max_frames = INT64_MAX; MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); for (i = 0; inb_max_frames; i++) { @@ -1240,29 +1470,55 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->copy_prior_start = -1; MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); - MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st); - while (bsf) { - char *arg = NULL; - if (next = strchr(bsf, ',')) - *next++ = 0; - if (arg = strchr(bsf, '=')) - *arg++ = 0; - if (!(bsfc = av_bitstream_filter_init(bsf))) { - av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf); + MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); + while (bsfs && *bsfs) { + const AVBitStreamFilter *filter; + char *bsf, *bsf_options_str, *bsf_name; + + bsf = av_get_token(&bsfs, ","); + if (!bsf) + exit_program(1); + bsf_name = av_strtok(bsf, "=", &bsf_options_str); + if (!bsf_name) + exit_program(1); + + filter = av_bsf_get_by_name(bsf_name); + if (!filter) { + av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf_name); exit_program(1); } - if (bsfc_prev) - bsfc_prev->next = bsfc; - else - ost->bitstream_filters = bsfc; - if (arg) - if (!(bsfc->args = av_strdup(arg))) { - av_log(NULL, AV_LOG_FATAL, "Bitstream filter memory allocation failed\n"); + + ost->bsf_ctx = av_realloc_array(ost->bsf_ctx, + ost->nb_bitstream_filters + 1, + sizeof(*ost->bsf_ctx)); + if (!ost->bsf_ctx) + exit_program(1); + + ret = av_bsf_alloc(filter, &ost->bsf_ctx[ost->nb_bitstream_filters]); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter context\n"); + exit_program(1); + } + + ost->nb_bitstream_filters++; + + if (bsf_options_str && filter->priv_class) { + const AVOption *opt = av_opt_next(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, NULL); + const char * shorthand[2] = {NULL}; + + if (opt) + shorthand[0] = opt->name; + + ret = av_opt_set_from_string(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, bsf_options_str, shorthand, "=", ":"); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error parsing options for bitstream filter %s\n", bsf_name); exit_program(1); } + } + av_freep(&bsf); - bsfc_prev = bsfc; - bsf = next; + if (*bsfs) + bsfs++; } MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); @@ -1270,7 +1526,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e uint32_t tag = strtol(codec_tag, &next, 0); if (*next) tag = AV_RL32(codec_tag); - ost->st->codec->codec_tag = + ost->st->codecpar->codec_tag = ost->enc_ctx->codec_tag = tag; } @@ -1283,6 +1539,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e MATCH_PER_STREAM_OPT(disposition, str, ost->disposition, oc, st); ost->disposition = av_strdup(ost->disposition); + ost->max_muxing_queue_size = 128; + MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); + ost->max_muxing_queue_size *= sizeof(AVPacket); + if (oc->oformat->flags & AVFMT_GLOBALHEADER) ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -1302,6 +1562,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e } ost->last_mux_dts = AV_NOPTS_VALUE; + ost->muxing_queue = av_fifo_alloc(8 * sizeof(AVPacket)); + if (!ost->muxing_queue) + exit_program(1); + return ost; } @@ -1367,7 +1631,7 @@ static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc, else if (ost->filters) return av_strdup(ost->filters); - return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ? + return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? "null" : "anull"); } @@ -1417,6 +1681,8 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); + if (o->nb_filters > 1) + av_log(NULL, AV_LOG_ERROR, "Only '-vf %s' read, ignoring remaining -vf options: Use ',' to separate filters\n", ost->filters); if (!ost->stream_copy) { const char *p = NULL; @@ -1463,7 +1729,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for intra matrix.\n"); exit_program(1); } - av_codec_set_chroma_intra_matrix(video_enc, p); + video_enc->chroma_intra_matrix = p; parse_matrix_coeffs(p, chroma_intra_matrix); } MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); @@ -1598,6 +1864,8 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); + if (o->nb_filters > 1) + av_log(NULL, AV_LOG_ERROR, "Only '-af %s' read, ignoring remaining -af options: Use ',' to separate filters\n", ost->filters); if (!ost->stream_copy) { char *sample_fmt = NULL; @@ -1783,56 +2051,6 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) return 0; } -static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename) -{ - int i, err; - AVFormatContext *ic = avformat_alloc_context(); - - ic->interrupt_callback = int_cb; - err = avformat_open_input(&ic, filename, NULL, NULL); - if (err < 0) - return err; - /* copy stream format */ - for(i=0;inb_streams;i++) { - AVStream *st; - OutputStream *ost; - AVCodec *codec; - const char *enc_config; - - codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id); - if (!codec) { - av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codec->codec_id); - return AVERROR(EINVAL); - } - if (codec->type == AVMEDIA_TYPE_AUDIO) - opt_audio_codec(o, "c:a", codec->name); - else if (codec->type == AVMEDIA_TYPE_VIDEO) - opt_video_codec(o, "c:v", codec->name); - ost = new_output_stream(o, s, codec->type, -1); - st = ost->st; - - avcodec_get_context_defaults3(st->codec, codec); - enc_config = av_stream_get_recommended_encoder_configuration(ic->streams[i]); - if (enc_config) { - AVDictionary *opts = NULL; - av_dict_parse_string(&opts, enc_config, "=", ",", 0); - av_opt_set_dict2(st->codec, &opts, AV_OPT_SEARCH_CHILDREN); - av_dict_free(&opts); - } - - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy) - choose_sample_fmt(st, codec); - else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy) - choose_pixel_fmt(st, st->codec, codec, st->codec->pix_fmt); - avcodec_copy_context(ost->enc_ctx, st->codec); - if (enc_config) - av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0); - } - - avformat_close_input(&ic); - return err; -} - static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, AVFormatContext *oc) { @@ -1851,6 +2069,7 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, ost->filter = ofilter; ofilter->ost = ost; + ofilter->format = -1; if (ost->stream_copy) { av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, " @@ -1886,28 +2105,16 @@ static int init_complex_filters(void) return 0; } -static int configure_complex_filters(void) -{ - int i, ret = 0; - - for (i = 0; i < nb_filtergraphs; i++) - if (!filtergraphs[i]->graph && - (ret = configure_filtergraph(filtergraphs[i])) < 0) - return ret; - return 0; -} - static int open_output_file(OptionsContext *o, const char *filename) { AVFormatContext *oc; int i, j, err; - AVOutputFormat *file_oformat; OutputFile *of; OutputStream *ost; InputStream *ist; AVDictionary *unused_opts = NULL; AVDictionaryEntry *e = NULL; - + int format_flags = 0; if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { o->stop_time = INT64_MAX; @@ -1950,9 +2157,18 @@ static int open_output_file(OptionsContext *o, const char *filename) if (o->recording_time != INT64_MAX) oc->duration = o->recording_time; - file_oformat= oc->oformat; oc->interrupt_callback = int_cb; + e = av_dict_get(o->g->format_opts, "fflags", NULL, 0); + if (e) { + const AVOption *o = av_opt_find(oc, "fflags", NULL, 0, 0); + av_opt_eval_flags(oc, o, e->value, &format_flags); + } + if (o->bitexact) { + format_flags |= AVFMT_FLAG_BITEXACT; + oc->flags |= AVFMT_FLAG_BITEXACT; + } + /* create streams for all unlabeled output pads */ for (i = 0; i < nb_filtergraphs; i++) { FilterGraph *fg = filtergraphs[i]; @@ -1971,46 +2187,7 @@ static int open_output_file(OptionsContext *o, const char *filename) } } - /* ffserver seeking with date=... needs a date reference */ - if (!strcmp(file_oformat->name, "ffm") && - av_strstart(filename, "http:", NULL)) { - int err = parse_option(o, "metadata", "creation_time=now", options); - if (err < 0) { - print_error(filename, err); - exit_program(1); - } - } - - if (!strcmp(file_oformat->name, "ffm") && !override_ffserver && - av_strstart(filename, "http:", NULL)) { - int j; - /* special case for files sent to ffserver: we get the stream - parameters from ffserver */ - int err = read_ffserver_streams(o, oc, filename); - if (err < 0) { - print_error(filename, err); - exit_program(1); - } - for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) { - ost = output_streams[j]; - for (i = 0; i < nb_input_streams; i++) { - ist = input_streams[i]; - if(ist->st->codec->codec_type == ost->st->codec->codec_type){ - ost->sync_ist= ist; - ost->source_index= i; - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull"); - if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null"); - ist->discard = 0; - ist->st->discard = ist->user_set_discard; - break; - } - } - if(!ost->sync_ist){ - av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type)); - exit_program(1); - } - } - } else if (!o->nb_stream_maps) { + if (!o->nb_stream_maps) { char *subtitle_codec_name = NULL; /* pick the "best" stream of each type */ @@ -2021,10 +2198,13 @@ static int open_output_file(OptionsContext *o, const char *filename) for (i = 0; i < nb_input_streams; i++) { int new_area; ist = input_streams[i]; - new_area = ist->st->codec->width * ist->st->codec->height + 100000000*!!ist->st->codec_info_nb_frames; + new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames + + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); + if (ist->user_set_discard == AVDISCARD_ALL) + continue; if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) new_area = 1; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && new_area > area) { if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) continue; @@ -2042,8 +2222,11 @@ static int open_output_file(OptionsContext *o, const char *filename) for (i = 0; i < nb_input_streams; i++) { int score; ist = input_streams[i]; - score = ist->st->codec->channels + 100000000*!!ist->st->codec_info_nb_frames; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && + score = ist->st->codecpar->channels + 100000000*!!ist->st->codec_info_nb_frames + + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); + if (ist->user_set_discard == AVDISCARD_ALL) + continue; + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && score > best_score) { best_score = score; idx = i; @@ -2057,13 +2240,15 @@ static int open_output_file(OptionsContext *o, const char *filename) MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s"); if (!o->subtitle_disable && (avcodec_find_encoder(oc->oformat->subtitle_codec) || subtitle_codec_name)) { for (i = 0; i < nb_input_streams; i++) - if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { + if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { AVCodecDescriptor const *input_descriptor = - avcodec_descriptor_get(input_streams[i]->st->codec->codec_id); + avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id); AVCodecDescriptor const *output_descriptor = NULL; AVCodec const *output_codec = avcodec_find_encoder(oc->oformat->subtitle_codec); int input_props = 0, output_props = 0; + if (input_streams[i]->user_set_discard == AVDISCARD_ALL) + continue; if (output_codec) output_descriptor = avcodec_descriptor_get(output_codec->id); if (input_descriptor) @@ -2085,8 +2270,10 @@ static int open_output_file(OptionsContext *o, const char *filename) if (!o->data_disable ) { enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_DATA); for (i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) { - if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_DATA - && input_streams[i]->st->codec->codec_id == codec_id ) + if (input_streams[i]->user_set_discard == AVDISCARD_ALL) + continue; + if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA + && input_streams[i]->st->codecpar->codec_id == codec_id ) new_data_stream(o, oc, i); } } @@ -2123,17 +2310,22 @@ loop_end: int src_idx = input_files[map->file_index]->ist_index + map->stream_index; ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index]; - if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) + if (ist->user_set_discard == AVDISCARD_ALL) { + av_log(NULL, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", + map->file_index, map->stream_index); + exit_program(1); + } + if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) continue; - if(o-> audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) continue; - if(o-> video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) continue; - if(o-> data_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_DATA) + if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) continue; ost = NULL; - switch (ist->st->codec->codec_type) { + switch (ist->st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: ost = new_video_stream (o, oc, src_idx); break; case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream (o, oc, src_idx); break; case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream (o, oc, src_idx); break; @@ -2188,17 +2380,17 @@ loop_end: avio_read(pb, attachment, len); ost = new_attachment_stream(o, oc, -1); - ost->stream_copy = 1; + ost->stream_copy = 0; ost->attachment_filename = o->attachments[i]; - ost->finished = 1; - ost->st->codec->extradata = attachment; - ost->st->codec->extradata_size = len; + ost->st->codecpar->extradata = attachment; + ost->st->codecpar->extradata_size = len; p = strrchr(o->attachments[i], '/'); av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); avio_closep(&pb); } +#if FF_API_LAVF_AVCTX for (i = nb_output_streams - oc->nb_streams; i < nb_output_streams; i++) { //for all streams of this output file AVDictionaryEntry *e; ost = output_streams[i]; @@ -2209,9 +2401,10 @@ loop_end: if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0) exit_program(1); } +#endif if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { - av_dump_format(oc, nb_output_files - 1, oc->filename, 1); + av_dump_format(oc, nb_output_files - 1, oc->url, 1); av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1); exit_program(1); } @@ -2258,21 +2451,93 @@ loop_end: } av_dict_free(&unused_opts); - /* set the encoding/decoding_needed flags */ + /* set the decoding_needed flags and create simple filtergraphs */ for (i = of->ost_index; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - ost->encoding_needed = !ost->stream_copy; if (ost->encoding_needed && ost->source_index >= 0) { InputStream *ist = input_streams[ost->source_index]; ist->decoding_needed |= DECODING_FOR_OST; + + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + err = init_simple_filtergraph(ist, ost); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Error initializing a simple filtergraph between streams " + "%d:%d->%d:%d\n", ist->file_index, ost->source_index, + nb_output_files - 1, ost->st->index); + exit_program(1); + } + } + } + + /* set the filter output constraints */ + if (ost->filter) { + OutputFilter *f = ost->filter; + int count; + switch (ost->enc_ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + f->frame_rate = ost->frame_rate; + f->width = ost->enc_ctx->width; + f->height = ost->enc_ctx->height; + if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { + f->format = ost->enc_ctx->pix_fmt; + } else if (ost->enc->pix_fmts) { + count = 0; + while (ost->enc->pix_fmts[count] != AV_PIX_FMT_NONE) + count++; + f->formats = av_mallocz_array(count + 1, sizeof(*f->formats)); + if (!f->formats) + exit_program(1); + memcpy(f->formats, ost->enc->pix_fmts, (count + 1) * sizeof(*f->formats)); + } + break; + case AVMEDIA_TYPE_AUDIO: + if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { + f->format = ost->enc_ctx->sample_fmt; + } else if (ost->enc->sample_fmts) { + count = 0; + while (ost->enc->sample_fmts[count] != AV_SAMPLE_FMT_NONE) + count++; + f->formats = av_mallocz_array(count + 1, sizeof(*f->formats)); + if (!f->formats) + exit_program(1); + memcpy(f->formats, ost->enc->sample_fmts, (count + 1) * sizeof(*f->formats)); + } + if (ost->enc_ctx->sample_rate) { + f->sample_rate = ost->enc_ctx->sample_rate; + } else if (ost->enc->supported_samplerates) { + count = 0; + while (ost->enc->supported_samplerates[count]) + count++; + f->sample_rates = av_mallocz_array(count + 1, sizeof(*f->sample_rates)); + if (!f->sample_rates) + exit_program(1); + memcpy(f->sample_rates, ost->enc->supported_samplerates, + (count + 1) * sizeof(*f->sample_rates)); + } + if (ost->enc_ctx->channels) { + f->channel_layout = av_get_default_channel_layout(ost->enc_ctx->channels); + } else if (ost->enc->channel_layouts) { + count = 0; + while (ost->enc->channel_layouts[count]) + count++; + f->channel_layouts = av_mallocz_array(count + 1, sizeof(*f->channel_layouts)); + if (!f->channel_layouts) + exit_program(1); + memcpy(f->channel_layouts, ost->enc->channel_layouts, + (count + 1) * sizeof(*f->channel_layouts)); + } + break; + } } } /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER) { - if (!av_filename_number_test(oc->filename)) { - print_error(oc->filename, AVERROR(EINVAL)); + if (!av_filename_number_test(oc->url)) { + print_error(oc->url, AVERROR(EINVAL)); exit_program(1); } } @@ -2353,8 +2618,6 @@ loop_end: av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); if (!output_streams[i]->stream_copy) { av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0); - if (ist->autorotate) - av_dict_set(&output_streams[i]->st->metadata, "rotate", NULL, 0); } } @@ -2430,7 +2693,6 @@ loop_end: char type, *val; const char *stream_spec; int index = 0, j, ret = 0; - char now_time[256]; val = strchr(o->metadata[i].u.str, '='); if (!val) { @@ -2440,25 +2702,20 @@ loop_end: } *val++ = 0; - if (!strcmp(o->metadata[i].u.str, "creation_time") && - !strcmp(val, "now")) { - time_t now = time(0); - struct tm *ptm, tmbuf; - ptm = localtime_r(&now, &tmbuf); - if (ptm) { - if (strftime(now_time, sizeof(now_time), "%Y-%m-%d %H:%M:%S", ptm)) - val = now_time; - } - } - parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec); if (type == 's') { for (j = 0; j < oc->nb_streams; j++) { ost = output_streams[nb_output_streams - oc->nb_streams + j]; if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) { - av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0); if (!strcmp(o->metadata[i].u.str, "rotate")) { - ost->rotate_overridden = 1; + char *tail; + double theta = av_strtod(val, &tail); + if (!*tail) { + ost->rotate_overridden = 1; + ost->rotate_override_value = theta; + } + } else { + av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0); } } else if (ret < 0) exit_program(1); @@ -2515,11 +2772,10 @@ static int opt_target(void *optctx, const char *opt, const char *arg) int i, j, fr; for (j = 0; j < nb_input_files; j++) { for (i = 0; i < input_files[j]->nb_streams; i++) { - AVCodecContext *c = input_files[j]->ctx->streams[i]->codec; - if (c->codec_type != AVMEDIA_TYPE_VIDEO || - !c->time_base.num) + AVStream *st = input_files[j]->ctx->streams[i]; + if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) continue; - fr = c->time_base.den * 1000 / c->time_base.num; + fr = st->time_base.den * 1000 / st->time_base.num; if (fr == 25000) { norm = PAL; break; @@ -2830,7 +3086,7 @@ static int opt_timecode(void *optctx, const char *opt, const char *arg) if (ret >= 0) ret = av_dict_set(&o->g->codec_opts, "gop_timecode", arg, 0); av_free(tcr); - return 0; + return ret; } static int opt_channel_layout(void *optctx, const char *opt, const char *arg) @@ -2928,7 +3184,7 @@ void show_help_default(const char *opt, const char *arg) " -h -- print basic options\n" " -h long -- print more options\n" " -h full -- print all options (including all format and codec specific options, very long)\n" - " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter\n" + " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf\n" " See man %s for detailed description of the options.\n" "\n", program_name); @@ -2971,8 +3227,11 @@ void show_help_default(const char *opt, const char *arg) #if CONFIG_SWSCALE show_help_children(sws_get_class(), flags); #endif +#if CONFIG_SWRESAMPLE show_help_children(swr_get_class(), AV_OPT_FLAG_AUDIO_PARAM); +#endif show_help_children(avfilter_get_class(), AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM); + show_help_children(av_bsf_get_class(), AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_BSF_PARAM); } } @@ -2989,8 +3248,8 @@ enum OptGroup { }; static const OptionGroupDef groups[] = { - [GROUP_OUTFILE] = { "output file", NULL, OPT_OUTPUT }, - [GROUP_INFILE] = { "input file", "i", OPT_INPUT }, + [GROUP_OUTFILE] = { "output url", NULL, OPT_OUTPUT }, + [GROUP_INFILE] = { "input url", "i", OPT_INPUT }, }; static int open_files(OptionGroupList *l, const char *inout, @@ -3049,6 +3308,9 @@ int ffmpeg_parse_options(int argc, char **argv) goto fail; } + /* configure terminal and setup signal handlers */ + term_init(); + /* open input files */ ret = open_files(&octx.groups[GROUP_INFILE], "input", open_input_file); if (ret < 0) { @@ -3070,12 +3332,7 @@ int ffmpeg_parse_options(int argc, char **argv) goto fail; } - /* configure the complex filtergraphs */ - ret = configure_complex_filters(); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error configuring complex filters.\n"); - goto fail; - } + check_filter_outputs(); fail: uninit_parse_context(&octx); @@ -3106,7 +3363,7 @@ static int opt_progress(void *optctx, const char *opt, const char *arg) #define OFFSET(x) offsetof(OptionsContext, x) const OptionDef options[] = { /* main options */ -#include "ffmpeg/cmdutils_common_opts.h" + CMDUTILS_COMMON_OPTIONS { "f", HAS_ARG | OPT_STRING | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(format) }, "force format", "fmt" }, @@ -3144,7 +3401,7 @@ const OptionDef options[] = { OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(recording_time) }, "record or transcode \"duration\" seconds of audio/video", "duration" }, - { "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(stop_time) }, + { "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(stop_time) }, "record or transcode stop time", "time_stop" }, { "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(limit_filesize) }, "set the limit file size in bytes", "limit_size" }, @@ -3152,7 +3409,7 @@ const OptionDef options[] = { OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(start_time) }, "set the start time offset", "time_off" }, { "sseof", HAS_ARG | OPT_TIME | OPT_OFFSET | - OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(start_time_eof) }, + OPT_INPUT, { .off = OFFSET(start_time_eof) }, "set the start time offset relative to EOF", "time_off" }, { "seek_timestamp", HAS_ARG | OPT_INT | OPT_OFFSET | OPT_INPUT, { .off = OFFSET(seek_timestamp) }, @@ -3212,6 +3469,9 @@ const OptionDef options[] = { { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(shortest) }, "finish encoding within shortest input" }, + { "bitexact", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | + OPT_OUTPUT | OPT_INPUT, { .off = OFFSET(bitexact) }, + "bitexact mode" }, { "apad", OPT_STRING | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(apad) }, "audio pad", "" }, @@ -3243,12 +3503,16 @@ const OptionDef options[] = { "set profile", "profile" }, { "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) }, "set stream filtergraph", "filter_graph" }, + { "filter_threads", HAS_ARG | OPT_INT, { &filter_nbthreads }, + "number of non-complex filter threads" }, { "filter_script", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) }, "read stream filtergraph description from a file", "filename" }, { "reinit_filter", HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(reinit_filters) }, "reinit filtergraph on input parameter changes", "" }, { "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, "create a complex filtergraph", "graph_description" }, + { "filter_complex_threads", HAS_ARG | OPT_INT, { &filter_complex_nbthreads }, + "number of threads for -filter_complex" }, { "lavfi", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, "create a complex filtergraph", "graph_description" }, { "filter_complex_script", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex_script }, @@ -3266,7 +3530,7 @@ const OptionDef options[] = { { "debug_ts", OPT_BOOL | OPT_EXPERT, { &debug_ts }, "print timestamp debugging info" }, { "max_error_rate", HAS_ARG | OPT_FLOAT, { &max_error_rate }, - "maximum error rate", "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success." }, + "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success.", "maximum error rate" }, { "discard", OPT_STRING | HAS_ARG | OPT_SPEC | OPT_INPUT, { .off = OFFSET(discard) }, "discard", "" }, @@ -3276,6 +3540,8 @@ const OptionDef options[] = { { "thread_queue_size", HAS_ARG | OPT_INT | OPT_OFFSET | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(thread_queue_size) }, "set the maximum number of queued packets from the demuxer" }, + { "find_stream_info", OPT_BOOL | OPT_PERFILE | OPT_INPUT | OPT_EXPERT, { &find_stream_info }, + "read and decode the streams to fill missing information with heuristics" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -3323,6 +3589,8 @@ const OptionDef options[] = { "dump video coding statistics to file" }, { "vstats_file", OPT_VIDEO | HAS_ARG | OPT_EXPERT , { .func_arg = opt_vstats_file }, "dump video coding statistics to file", "file" }, + { "vstats_version", OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT , { &vstats_version }, + "Version of the vstats format to use."}, { "vf", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_filters }, "set video filters", "filter_graph" }, { "intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | @@ -3361,10 +3629,10 @@ const OptionDef options[] = { { "hwaccel_device", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_devices) }, "select a device for HW acceleration", "devicename" }, -#if HAVE_VDPAU_X11 - { "vdpau_api_ver", HAS_ARG | OPT_INT | OPT_EXPERT, { &vdpau_api_ver }, "" }, -#endif -#if CONFIG_VDA || CONFIG_VIDEOTOOLBOX + { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | + OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, + "select output format used with HW accelerated decoding", "format" }, +#if CONFIG_VIDEOTOOLBOX { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, #endif { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, @@ -3429,11 +3697,17 @@ const OptionDef options[] = { "set the maximum demux-decode delay", "seconds" }, { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) }, "set the initial demux-decode delay", "seconds" }, - { "override_ffserver", OPT_BOOL | OPT_EXPERT | OPT_OUTPUT, { &override_ffserver }, - "override the options from ffserver", "" }, { "sdp_file", HAS_ARG | OPT_EXPERT | OPT_OUTPUT, { .func_arg = opt_sdp_file }, "specify a file in which to print sdp information", "file" }, + { "time_base", HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(time_bases) }, + "set the desired time base hint for output stream (1:24, 1:48000 or 0.04166, 2.0833e-5)", "ratio" }, + { "enc_time_base", HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(enc_time_bases) }, + "set the desired time base for the encoder (1:24, 1:48000 or 0.04166, 2.0833e-5). " + "two special values are defined - " + "0 = use frame rate (video) or sample rate (audio)," + "-1 = match source time base", "ratio" }, + { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) }, "A comma-separated list of bitstream filters", "bitstream_filters" }, { "absf", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new }, @@ -3449,11 +3723,30 @@ const OptionDef options[] = { "set the subtitle options to the indicated preset", "preset" }, { "fpre", HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_preset }, "set options from indicated preset file", "filename" }, + + { "max_muxing_queue_size", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(max_muxing_queue_size) }, + "maximum number of packets that can be buffered while waiting for all streams to initialize", "packets" }, + /* data codec support */ { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec }, "force data codec ('copy' to copy stream)", "codec" }, { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(data_disable) }, "disable data" }, +#if CONFIG_VAAPI + { "vaapi_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vaapi_device }, + "set VAAPI hardware device (DRM path or X11 display name)", "device" }, +#endif + +#if CONFIG_QSV + { "qsv_device", HAS_ARG | OPT_STRING | OPT_EXPERT, { &qsv_device }, + "set QSV hardware device (DirectX adapter index, DRM path or X11 display name)", "device"}, +#endif + + { "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device }, + "initialise hardware device", "args" }, + { "filter_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_hw_device }, + "set hardware device used when filtering", "device" }, + { NULL, }, }; diff --git a/app/src/main/cpp/ffmpeg/ffprobe.c b/app/src/main/cpp/ffmpeg/ffprobe.c index 52b4db6..b41d3ef 100644 --- a/app/src/main/cpp/ffmpeg/ffprobe.c +++ b/app/src/main/cpp/ffmpeg/ffprobe.c @@ -35,8 +35,10 @@ #include "libavutil/bprint.h" #include "libavutil/display.h" #include "libavutil/hash.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "libavutil/dict.h" #include "libavutil/intreadwrite.h" @@ -48,6 +50,19 @@ #include "libswresample/swresample.h" #include "libpostproc/postprocess.h" #include "cmdutils.h" + +#include "libavutil/thread.h" + +#if !HAVE_THREADS +# ifdef pthread_mutex_lock +# undef pthread_mutex_lock +# endif +# define pthread_mutex_lock(a) do{}while(0) +# ifdef pthread_mutex_unlock +# undef pthread_mutex_unlock +# endif +# define pthread_mutex_unlock(a) do{}while(0) +#endif #include "ffprobe.h" typedef struct InputStream { @@ -85,6 +100,7 @@ static int do_show_library_versions = 0; static int do_show_pixel_formats = 0; static int do_show_pixel_format_flags = 0; static int do_show_pixel_format_components = 0; +static int do_show_log = 0; static int do_show_chapter_tags = 0; static int do_show_format_tags = 0; @@ -114,6 +130,8 @@ typedef struct ReadInterval { static ReadInterval *read_intervals; static int read_intervals_nb = 0; +static int find_stream_info = 1; + /* section structure definition */ #define SECTION_MAX_NB_CHILDREN 10 @@ -147,6 +165,10 @@ typedef enum { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_SIDE_DATA, + SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, + SECTION_ID_FRAME_SIDE_DATA_TIMECODE, + SECTION_ID_FRAME_LOG, + SECTION_ID_FRAME_LOGS, SECTION_ID_LIBRARY_VERSION, SECTION_ID_LIBRARY_VERSIONS, SECTION_ID_PACKET, @@ -186,17 +208,21 @@ static struct section sections[] = { [SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } }, [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" }, [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } }, - [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, -1 } }, + [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } }, [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" }, - [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 } }, - [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" }, + [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } }, + [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } }, + [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, }, [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } }, [SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } }, [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} }, [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} }, [SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } }, [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" }, - [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 } }, + [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" }, [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", 0, { -1 } }, [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } }, [SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } }, @@ -219,7 +245,7 @@ static struct section sections[] = { [SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } }, [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" }, [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" }, - [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 } }, + [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" }, [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", 0, { -1 } }, [SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } }, }; @@ -256,6 +282,21 @@ static uint64_t *nb_streams_packets; static uint64_t *nb_streams_frames; static int *selected_streams; +#if HAVE_THREADS +pthread_mutex_t log_mutex; +#endif +typedef struct LogBuffer { + char *context_name; + int log_level; + char *log_message; + AVClassCategory category; + char *parent_name; + AVClassCategory parent_category; +}LogBuffer; + +static LogBuffer *log_buffer; +static int log_buffer_size; + static int buffer_length = 0; static int buffer_size = 256 * 1024; char *print_buffer = NULL; @@ -329,6 +370,54 @@ void frank_printf_json(char *fmt, ...) { va_end(args); } +static void log_callback(void *ptr, int level, const char *fmt, va_list vl) +{ + AVClass* avc = ptr ? *(AVClass **) ptr : NULL; + va_list vl2; + char line[1024]; + static int print_prefix = 1; + void *new_log_buffer; + + va_copy(vl2, vl); + av_log_default_callback(ptr, level, fmt, vl); + av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix); + va_end(vl2); + +#if HAVE_THREADS + pthread_mutex_lock(&log_mutex); + + new_log_buffer = av_realloc_array(log_buffer, log_buffer_size + 1, sizeof(*log_buffer)); + if (new_log_buffer) { + char *msg; + int i; + + log_buffer = new_log_buffer; + memset(&log_buffer[log_buffer_size], 0, sizeof(log_buffer[log_buffer_size])); + log_buffer[log_buffer_size].context_name= avc ? av_strdup(avc->item_name(ptr)) : NULL; + if (avc) { + if (avc->get_category) log_buffer[log_buffer_size].category = avc->get_category(ptr); + else log_buffer[log_buffer_size].category = avc->category; + } + log_buffer[log_buffer_size].log_level = level; + msg = log_buffer[log_buffer_size].log_message = av_strdup(line); + for (i=strlen(msg) - 1; i>=0 && msg[i] == '\n'; i--) { + msg[i] = 0; + } + if (avc && avc->parent_log_context_offset) { + AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) + + avc->parent_log_context_offset); + if (parent && *parent) { + log_buffer[log_buffer_size].parent_name = av_strdup((*parent)->item_name(parent)); + log_buffer[log_buffer_size].parent_category = + (*parent)->get_category ? (*parent)->get_category(parent) :(*parent)->category; + } + } + log_buffer_size ++; + } + + pthread_mutex_unlock(&log_mutex); +#endif +} static void ffprobe_cleanup(int ret) { @@ -337,6 +426,9 @@ static void ffprobe_cleanup(int ret) av_dict_free(&(sections[i].entries_to_show)); buffer_length = 0; +#if HAVE_THREADS + pthread_mutex_destroy(&log_mutex); +#endif } struct unit_value { @@ -1837,6 +1929,7 @@ static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id } static void print_pkt_side_data(WriterContext *w, + AVCodecParameters *par, const AVPacketSideData *side_data, int nb_side_data, SectionID id_data_list, @@ -1844,32 +1937,77 @@ static void print_pkt_side_data(WriterContext *w, { int i; - writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA_LIST); + writer_print_section_header(w, id_data_list); for (i = 0; i < nb_side_data; i++) { const AVPacketSideData *sd = &side_data[i]; const char *name = av_packet_side_data_name(sd->type); - writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA); + writer_print_section_header(w, id_data); print_str("side_data_type", name ? name : "unknown"); - print_int("side_data_size", sd->size); if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) { writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1); print_int("rotation", av_display_rotation_get((int32_t *)sd->data)); } else if (sd->type == AV_PKT_DATA_STEREO3D) { const AVStereo3D *stereo = (AVStereo3D *)sd->data; -// print_str("type", av_stereo3d_type_name(stereo->type));//TODO + print_str("type", av_stereo3d_type_name(stereo->type)); print_int("inverted", !!(stereo->flags & AV_STEREO3D_FLAG_INVERT)); + } else if (sd->type == AV_PKT_DATA_SPHERICAL) { + const AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; + print_str("projection", av_spherical_projection_name(spherical->projection)); + if (spherical->projection == AV_SPHERICAL_CUBEMAP) { + print_int("padding", spherical->padding); + } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { + size_t l, t, r, b; + av_spherical_tile_bounds(spherical, par->width, par->height, + &l, &t, &r, &b); + print_int("bound_left", l); + print_int("bound_top", t); + print_int("bound_right", r); + print_int("bound_bottom", b); + } + + print_int("yaw", (double) spherical->yaw / (1 << 16)); + print_int("pitch", (double) spherical->pitch / (1 << 16)); + print_int("roll", (double) spherical->roll / (1 << 16)); + } else if (sd->type == AV_PKT_DATA_SKIP_SAMPLES && sd->size == 10) { + print_int("skip_samples", AV_RL32(sd->data)); + print_int("discard_padding", AV_RL32(sd->data + 4)); + print_int("skip_reason", AV_RL8(sd->data + 8)); + print_int("discard_reason", AV_RL8(sd->data + 9)); + } else if (sd->type == AV_PKT_DATA_MASTERING_DISPLAY_METADATA) { + AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data; + + if (metadata->has_primaries) { + print_q("red_x", metadata->display_primaries[0][0], '/'); + print_q("red_y", metadata->display_primaries[0][1], '/'); + print_q("green_x", metadata->display_primaries[1][0], '/'); + print_q("green_y", metadata->display_primaries[1][1], '/'); + print_q("blue_x", metadata->display_primaries[2][0], '/'); + print_q("blue_y", metadata->display_primaries[2][1], '/'); + + print_q("white_point_x", metadata->white_point[0], '/'); + print_q("white_point_y", metadata->white_point[1], '/'); + } + + if (metadata->has_luminance) { + print_q("min_luminance", metadata->min_luminance, '/'); + print_q("max_luminance", metadata->max_luminance, '/'); + } + } else if (sd->type == AV_PKT_DATA_CONTENT_LIGHT_LEVEL) { + AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data; + print_int("max_content", metadata->MaxCLL); + print_int("max_average", metadata->MaxFALL); } writer_print_section_footer(w); } writer_print_section_footer(w); } -static void print_color_range(WriterContext *w, enum AVColorRange color_range, const char *fallback) +static void print_color_range(WriterContext *w, enum AVColorRange color_range) { const char *val = av_color_range_name(color_range); if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) { - print_str_opt("color_range", fallback); + print_str_opt("color_range", "unknown"); } else { print_str("color_range", val); } @@ -1915,6 +2053,58 @@ static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma } } + +static void clear_log(int need_lock) +{ + int i; + + if (need_lock) + pthread_mutex_lock(&log_mutex); + for (i=0; icodec->codec_type); + s = av_get_media_type_string(st->codecpar->codec_type); if (s) print_str ("codec_type", s); else print_str_opt("codec_type", "unknown"); print_int("stream_index", pkt->stream_index); @@ -1941,9 +2131,8 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p print_val("size", pkt->size, unit_byte_str); if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos); else print_str_opt("pos", "N/A"); -// print_fmt("flags", "%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_', -// pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_'); - print_fmt("flags", "%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_'); + print_fmt("flags", "%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_', + pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_'); if (pkt->side_data_elems) { int size; @@ -1957,7 +2146,7 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p av_dict_free(&dict); } - print_pkt_side_data(w, pkt->side_data, pkt->side_data_elems, + print_pkt_side_data(w, st->codecpar, pkt->side_data, pkt->side_data_elems, SECTION_ID_PACKET_SIDE_DATA_LIST, SECTION_ID_PACKET_SIDE_DATA); } @@ -2006,7 +2195,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, writer_print_section_header(w, SECTION_ID_FRAME); - s = av_get_media_type_string(stream->codec->codec_type); + s = av_get_media_type_string(stream->codecpar->codec_type); if (s) print_str ("media_type", s); else print_str_opt("media_type", "unknown"); print_int("stream_index", stream->index); @@ -2015,16 +2204,16 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_time("pkt_pts_time", frame->pts, &stream->time_base); print_ts ("pkt_dts", frame->pkt_dts); print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base); - print_ts ("best_effort_timestamp", av_frame_get_best_effort_timestamp(frame)); - print_time("best_effort_timestamp_time", av_frame_get_best_effort_timestamp(frame), &stream->time_base); - print_duration_ts ("pkt_duration", av_frame_get_pkt_duration(frame)); - print_duration_time("pkt_duration_time", av_frame_get_pkt_duration(frame), &stream->time_base); - if (av_frame_get_pkt_pos (frame) != -1) print_fmt ("pkt_pos", "%"PRId64, av_frame_get_pkt_pos(frame)); + print_ts ("best_effort_timestamp", frame->best_effort_timestamp); + print_time("best_effort_timestamp_time", frame->best_effort_timestamp, &stream->time_base); + print_duration_ts ("pkt_duration", frame->pkt_duration); + print_duration_time("pkt_duration_time", frame->pkt_duration, &stream->time_base); + if (frame->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, frame->pkt_pos); else print_str_opt("pkt_pos", "N/A"); - if (av_frame_get_pkt_size(frame) != -1) print_val ("pkt_size", av_frame_get_pkt_size(frame), unit_byte_str); + if (frame->pkt_size != -1) print_val ("pkt_size", frame->pkt_size, unit_byte_str); else print_str_opt("pkt_size", "N/A"); - switch (stream->codec->codec_type) { + switch (stream->codecpar->codec_type) { AVRational sar; case AVMEDIA_TYPE_VIDEO: @@ -2045,6 +2234,12 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_int("interlaced_frame", frame->interlaced_frame); print_int("top_field_first", frame->top_field_first); print_int("repeat_pict", frame->repeat_pict); + + print_color_range(w, frame->color_range); + print_color_space(w, frame->colorspace); + print_primaries(w, frame->color_primaries); + print_color_trc(w, frame->color_trc); + print_chroma_location(w, frame->chroma_location); break; case AVMEDIA_TYPE_AUDIO: @@ -2052,18 +2247,20 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, if (s) print_str ("sample_fmt", s); else print_str_opt("sample_fmt", "unknown"); print_int("nb_samples", frame->nb_samples); - print_int("channels", av_frame_get_channels(frame)); - if (av_frame_get_channel_layout(frame)) { + print_int("channels", frame->channels); + if (frame->channel_layout) { av_bprint_clear(&pbuf); - av_bprint_channel_layout(&pbuf, av_frame_get_channels(frame), - av_frame_get_channel_layout(frame)); + av_bprint_channel_layout(&pbuf, frame->channels, + frame->channel_layout); print_str ("channel_layout", pbuf.str); } else print_str_opt("channel_layout", "unknown"); break; } if (do_show_frame_tags) - show_tags(w, av_frame_get_metadata(frame), SECTION_ID_FRAME_TAGS); + show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS); + if (do_show_log) + show_log(w, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log); if (frame->nb_side_data) { writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_LIST); for (i = 0; i < frame->nb_side_data; i++) { @@ -2073,7 +2270,6 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA); name = av_frame_side_data_name(sd->type); print_str("side_data_type", name ? name : "unknown"); - print_int("side_data_size", sd->size); if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) { writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1); print_int("rotation", av_display_rotation_get((int32_t *)sd->data)); @@ -2081,6 +2277,46 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, char tcbuf[AV_TIMECODE_STR_SIZE]; av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data)); print_str("timecode", tcbuf); + } else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) { + uint32_t *tc = (uint32_t*)sd->data; + int m = FFMIN(tc[0],3); + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST); + for (int j = 1; j <= m ; j++) { + char tcbuf[AV_TIMECODE_STR_SIZE]; + av_timecode_make_smpte_tc_string(tcbuf, tc[j], 0); + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_TIMECODE); + print_str("value", tcbuf); + writer_print_section_footer(w); + } + writer_print_section_footer(w); + } else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) { + AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data; + + if (metadata->has_primaries) { + print_q("red_x", metadata->display_primaries[0][0], '/'); + print_q("red_y", metadata->display_primaries[0][1], '/'); + print_q("green_x", metadata->display_primaries[1][0], '/'); + print_q("green_y", metadata->display_primaries[1][1], '/'); + print_q("blue_x", metadata->display_primaries[2][0], '/'); + print_q("blue_y", metadata->display_primaries[2][1], '/'); + + print_q("white_point_x", metadata->white_point[0], '/'); + print_q("white_point_y", metadata->white_point[1], '/'); + } + + if (metadata->has_luminance) { + print_q("min_luminance", metadata->min_luminance, '/'); + print_q("max_luminance", metadata->max_luminance, '/'); + } + } else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) { + AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data; + print_int("max_content", metadata->MaxCLL); + print_int("max_average", metadata->MaxFALL); + } else if (sd->type == AV_FRAME_DATA_ICC_PROFILE) { + AVDictionaryEntry *tag = av_dict_get(sd->metadata, "name", NULL, AV_DICT_MATCH_CASE); + if (tag) + print_str(tag->key, tag->value); + print_int("size", sd->size); } writer_print_section_footer(w); } @@ -2095,36 +2331,55 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, static av_always_inline int process_frame(WriterContext *w, InputFile *ifile, - AVFrame *frame, AVPacket *pkt) + AVFrame *frame, AVPacket *pkt, + int *packet_new) { AVFormatContext *fmt_ctx = ifile->fmt_ctx; AVCodecContext *dec_ctx = ifile->streams[pkt->stream_index].dec_ctx; + AVCodecParameters *par = ifile->streams[pkt->stream_index].st->codecpar; AVSubtitle sub; int ret = 0, got_frame = 0; + clear_log(1); if (dec_ctx && dec_ctx->codec) { - switch (dec_ctx->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: - ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, pkt); - break; - case AVMEDIA_TYPE_AUDIO: - ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt); + if (*packet_new) { + ret = avcodec_send_packet(dec_ctx, pkt); + if (ret == AVERROR(EAGAIN)) { + ret = 0; + } else if (ret >= 0 || ret == AVERROR_EOF) { + ret = 0; + *packet_new = 0; + } + } + if (ret >= 0) { + ret = avcodec_receive_frame(dec_ctx, frame); + if (ret >= 0) { + got_frame = 1; + } else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + ret = 0; + } + } break; case AVMEDIA_TYPE_SUBTITLE: - ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt); + if (*packet_new) + ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt); + *packet_new = 0; break; + default: + *packet_new = 0; } + } else { + *packet_new = 0; } if (ret < 0) return ret; - ret = FFMIN(ret, pkt->size); /* guard against bogus return values */ - pkt->data += ret; - pkt->size -= ret; if (got_frame) { - int is_sub = (dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE); + int is_sub = (par->codec_type == AVMEDIA_TYPE_SUBTITLE); nb_streams_frames[pkt->stream_index]++; if (do_show_frames) if (is_sub) @@ -2134,7 +2389,7 @@ static av_always_inline int process_frame(WriterContext *w, if (is_sub) avsubtitle_free(&sub); } - return got_frame; + return got_frame || *packet_new; } static void log_read_interval(const ReadInterval *interval, void *log_ctx, int log_level) @@ -2165,7 +2420,7 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile, const ReadInterval *interval, int64_t *cur_ts) { AVFormatContext *fmt_ctx = ifile->fmt_ctx; - AVPacket pkt, pkt1; + AVPacket pkt; AVFrame *frame = NULL; int ret = 0, i = 0, frame_count = 0; int64_t start = -INT64_MAX, end = interval->end; @@ -2206,11 +2461,11 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile, goto end; } while (!av_read_frame(fmt_ctx, &pkt)) { - if (ifile->nb_streams > nb_streams) { + if (fmt_ctx->nb_streams > nb_streams) { REALLOCZ_ARRAY_STREAM(nb_streams_frames, nb_streams, fmt_ctx->nb_streams); REALLOCZ_ARRAY_STREAM(nb_streams_packets, nb_streams, fmt_ctx->nb_streams); REALLOCZ_ARRAY_STREAM(selected_streams, nb_streams, fmt_ctx->nb_streams); - nb_streams = ifile->nb_streams; + nb_streams = fmt_ctx->nb_streams; } if (selected_streams[pkt.stream_index]) { AVRational tb = ifile->streams[pkt.stream_index].st->time_base; @@ -2242,20 +2497,18 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile, nb_streams_packets[pkt.stream_index]++; } if (do_read_frames) { - pkt1 = pkt; - while (pkt1.size && process_frame(w, ifile, frame, &pkt1) > 0); + int packet_new = 1; + while (process_frame(w, ifile, frame, &pkt, &packet_new) > 0); } } av_packet_unref(&pkt); } - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; + av_packet_unref(&pkt); //Flush remaining frames that are cached in the decoder for (i = 0; i < fmt_ctx->nb_streams; i++) { pkt.stream_index = i; if (do_read_frames) - while (process_frame(w, ifile, frame, &pkt) > 0); + while (process_frame(w, ifile, frame, &pkt, &(int){1}) > 0); } end: @@ -2290,6 +2543,7 @@ static int read_packets(WriterContext *w, InputFile *ifile) static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program) { AVStream *stream = ist->st; + AVCodecParameters *par; AVCodecContext *dec_ctx; char val_str[128]; const char *s; @@ -2305,8 +2559,9 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id print_int("index", stream->index); + par = stream->codecpar; dec_ctx = ist->dec_ctx; - if (cd == avcodec_descriptor_get(dec_ctx->codec_id)) { + if (cd = avcodec_descriptor_get(par->codec_id)) { print_str("codec_name", cd->name); if (!do_bitexact) { print_str("codec_long_name", @@ -2319,18 +2574,18 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id } } - if (!do_bitexact && (profile = avcodec_profile_name(dec_ctx->codec_id, dec_ctx->profile))) + if (!do_bitexact && (profile = avcodec_profile_name(par->codec_id, par->profile))) print_str("profile", profile); else { - if (dec_ctx->profile != FF_PROFILE_UNKNOWN) { + if (par->profile != FF_PROFILE_UNKNOWN) { char profile_num[12]; - snprintf(profile_num, sizeof(profile_num), "%d", dec_ctx->profile); + snprintf(profile_num, sizeof(profile_num), "%d", par->profile); print_str("profile", profile_num); } else print_str_opt("profile", "unknown"); } - s = av_get_media_type_string(dec_ctx->codec_type); + s = av_get_media_type_string(par->codec_type); if (s) print_str ("codec_type", s); else print_str_opt("codec_type", "unknown"); #if FF_API_LAVF_AVCTX @@ -2339,51 +2594,52 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id #endif /* print AVI/FourCC tag */ - av_get_codec_tag_string(val_str, sizeof(val_str), dec_ctx->codec_tag); - print_str("codec_tag_string", val_str); - print_fmt("codec_tag", "0x%04x", dec_ctx->codec_tag); + print_str("codec_tag_string", av_fourcc2str(par->codec_tag)); + print_fmt("codec_tag", "0x%04"PRIx32, par->codec_tag); - switch (dec_ctx->codec_type) { + switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: - print_int("width", dec_ctx->width); - print_int("height", dec_ctx->height); + print_int("width", par->width); + print_int("height", par->height); +#if FF_API_LAVF_AVCTX if (dec_ctx) { print_int("coded_width", dec_ctx->coded_width); print_int("coded_height", dec_ctx->coded_height); } - print_int("has_b_frames", dec_ctx->has_b_frames); +#endif + print_int("has_b_frames", par->video_delay); sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL); - if (sar.den) { + if (sar.num) { print_q("sample_aspect_ratio", sar, ':'); av_reduce(&dar.num, &dar.den, - dec_ctx->width * sar.num, - dec_ctx->height * sar.den, + par->width * sar.num, + par->height * sar.den, 1024*1024); print_q("display_aspect_ratio", dar, ':'); } else { print_str_opt("sample_aspect_ratio", "N/A"); print_str_opt("display_aspect_ratio", "N/A"); } - s = av_get_pix_fmt_name(dec_ctx->pix_fmt); + s = av_get_pix_fmt_name(par->format); if (s) print_str ("pix_fmt", s); else print_str_opt("pix_fmt", "unknown"); - print_int("level", dec_ctx->level); + print_int("level", par->level); - print_color_range(w, dec_ctx->color_range, "N/A"); - print_color_space(w, dec_ctx->colorspace); - print_color_trc(w, dec_ctx->color_trc); - print_primaries(w, dec_ctx->color_primaries); - print_chroma_location(w, dec_ctx->chroma_sample_location); + print_color_range(w, par->color_range); + print_color_space(w, par->color_space); + print_color_trc(w, par->color_trc); + print_primaries(w, par->color_primaries); + print_chroma_location(w, par->chroma_location); - if (dec_ctx->field_order == AV_FIELD_PROGRESSIVE) + if (par->field_order == AV_FIELD_PROGRESSIVE) print_str("field_order", "progressive"); - else if (dec_ctx->field_order == AV_FIELD_TT) + else if (par->field_order == AV_FIELD_TT) print_str("field_order", "tt"); - else if (dec_ctx->field_order == AV_FIELD_BB) + else if (par->field_order == AV_FIELD_BB) print_str("field_order", "bb"); - else if (dec_ctx->field_order == AV_FIELD_TB) + else if (par->field_order == AV_FIELD_TB) print_str("field_order", "tb"); - else if (dec_ctx->field_order == AV_FIELD_BT) + else if (par->field_order == AV_FIELD_BT) print_str("field_order", "bt"); else print_str_opt("field_order", "unknown"); @@ -2402,30 +2658,30 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id break; case AVMEDIA_TYPE_AUDIO: - s = av_get_sample_fmt_name(dec_ctx->pix_fmt); + s = av_get_sample_fmt_name(par->format); if (s) print_str ("sample_fmt", s); else print_str_opt("sample_fmt", "unknown"); - print_val("sample_rate", dec_ctx->sample_rate, unit_hertz_str); - print_int("channels", dec_ctx->channels); + print_val("sample_rate", par->sample_rate, unit_hertz_str); + print_int("channels", par->channels); - if (dec_ctx->channel_layout) { + if (par->channel_layout) { av_bprint_clear(&pbuf); - av_bprint_channel_layout(&pbuf, dec_ctx->channels, dec_ctx->channel_layout); + av_bprint_channel_layout(&pbuf, par->channels, par->channel_layout); print_str ("channel_layout", pbuf.str); } else { print_str_opt("channel_layout", "unknown"); } - print_int("bits_per_sample", av_get_bits_per_sample(dec_ctx->codec_id)); + print_int("bits_per_sample", av_get_bits_per_sample(par->codec_id)); break; case AVMEDIA_TYPE_SUBTITLE: - if (dec_ctx->width) - print_int("width", dec_ctx->width); + if (par->width) + print_int("width", par->width); else print_str_opt("width", "N/A"); - if (dec_ctx->height) - print_int("height", dec_ctx->height); + if (par->height) + print_int("height", par->height); else print_str_opt("height", "N/A"); break; @@ -2452,7 +2708,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id print_time("start_time", stream->start_time, &stream->time_base); print_ts ("duration_ts", stream->duration); print_time("duration", stream->duration, &stream->time_base); - if (dec_ctx->bit_rate > 0) print_val ("bit_rate", dec_ctx->bit_rate, unit_bit_per_second_str); + if (par->bit_rate > 0) print_val ("bit_rate", par->bit_rate, unit_bit_per_second_str); else print_str_opt("bit_rate", "N/A"); #if FF_API_LAVF_AVCTX if (stream->codec->rc_max_rate > 0) print_val ("max_bit_rate", stream->codec->rc_max_rate, unit_bit_per_second_str); @@ -2467,10 +2723,10 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]); else print_str_opt("nb_read_packets", "N/A"); if (do_show_data) - writer_print_data(w, "extradata", dec_ctx->extradata, - dec_ctx->extradata_size); - writer_print_data_hash(w, "extradata_hash", dec_ctx->extradata, - dec_ctx->extradata_size); + writer_print_data(w, "extradata", par->extradata, + par->extradata_size); + writer_print_data_hash(w, "extradata_hash", par->extradata, + par->extradata_size); /* Print disposition information */ #define PRINT_DISPOSITION(flagname, name) do { \ @@ -2478,26 +2734,27 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id } while (0) if (do_show_stream_disposition) { - writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM_DISPOSITION : SECTION_ID_STREAM_DISPOSITION); - PRINT_DISPOSITION(DEFAULT, "default"); - PRINT_DISPOSITION(DUB, "dub"); - PRINT_DISPOSITION(ORIGINAL, "original"); - PRINT_DISPOSITION(COMMENT, "comment"); - PRINT_DISPOSITION(LYRICS, "lyrics"); - PRINT_DISPOSITION(KARAOKE, "karaoke"); - PRINT_DISPOSITION(FORCED, "forced"); - PRINT_DISPOSITION(HEARING_IMPAIRED, "hearing_impaired"); - PRINT_DISPOSITION(VISUAL_IMPAIRED, "visual_impaired"); - PRINT_DISPOSITION(CLEAN_EFFECTS, "clean_effects"); - PRINT_DISPOSITION(ATTACHED_PIC, "attached_pic"); - writer_print_section_footer(w); + writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM_DISPOSITION : SECTION_ID_STREAM_DISPOSITION); + PRINT_DISPOSITION(DEFAULT, "default"); + PRINT_DISPOSITION(DUB, "dub"); + PRINT_DISPOSITION(ORIGINAL, "original"); + PRINT_DISPOSITION(COMMENT, "comment"); + PRINT_DISPOSITION(LYRICS, "lyrics"); + PRINT_DISPOSITION(KARAOKE, "karaoke"); + PRINT_DISPOSITION(FORCED, "forced"); + PRINT_DISPOSITION(HEARING_IMPAIRED, "hearing_impaired"); + PRINT_DISPOSITION(VISUAL_IMPAIRED, "visual_impaired"); + PRINT_DISPOSITION(CLEAN_EFFECTS, "clean_effects"); + PRINT_DISPOSITION(ATTACHED_PIC, "attached_pic"); + PRINT_DISPOSITION(TIMED_THUMBNAILS, "timed_thumbnails"); + writer_print_section_footer(w); } if (do_show_stream_tags) ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS); if (stream->nb_side_data) { - print_pkt_side_data(w, stream->side_data, stream->nb_side_data, + print_pkt_side_data(w, stream->codecpar, stream->side_data, stream->nb_side_data, SECTION_ID_STREAM_SIDE_DATA_LIST, SECTION_ID_STREAM_SIDE_DATA); } @@ -2612,7 +2869,7 @@ static int show_format(WriterContext *w, InputFile *ifile) int ret = 0; writer_print_section_header(w, SECTION_ID_FORMAT); - print_str_validate("filename", fmt_ctx->filename); + print_str_validate("filename", fmt_ctx->url); print_int("nb_streams", fmt_ctx->nb_streams); print_int("nb_programs", fmt_ctx->nb_programs); print_str("format_name", fmt_ctx->iformat->name); @@ -2626,7 +2883,7 @@ static int show_format(WriterContext *w, InputFile *ifile) else print_str_opt("size", "N/A"); if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str); else print_str_opt("bit_rate", "N/A"); - print_int("probe_score", av_format_get_probe_score(fmt_ctx)); + print_int("probe_score", fmt_ctx->probe_score); if (do_show_format_tags) ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS); @@ -2651,12 +2908,17 @@ static void show_error(WriterContext *w, int err) static int open_input_file(InputFile *ifile, const char *filename) { - int err, i, orig_nb_streams; + int err, i; AVFormatContext *fmt_ctx = NULL; AVDictionaryEntry *t; - AVDictionary **opts; int scan_all_pmts_set = 0; + fmt_ctx = avformat_alloc_context(); + if (!fmt_ctx) { + print_error(filename, AVERROR(ENOMEM)); + exit_program(1); + } + if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) { av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE); scan_all_pmts_set = 1; @@ -2674,19 +2936,20 @@ static int open_input_file(InputFile *ifile, const char *filename) return AVERROR_OPTION_NOT_FOUND; } - /* fill the streams in the format context */ - opts = setup_find_stream_info_opts(fmt_ctx, codec_opts); - orig_nb_streams = fmt_ctx->nb_streams; + if (find_stream_info) { + AVDictionary **opts = setup_find_stream_info_opts(fmt_ctx, codec_opts); + int orig_nb_streams = fmt_ctx->nb_streams; - err = avformat_find_stream_info(fmt_ctx, opts); + err = avformat_find_stream_info(fmt_ctx, opts); - for (i = 0; i < orig_nb_streams; i++) - av_dict_free(&opts[i]); - av_freep(&opts); + for (i = 0; i < orig_nb_streams; i++) + av_dict_free(&opts[i]); + av_freep(&opts); - if (err < 0) { - print_error(filename, err); - return err; + if (err < 0) { + print_error(filename, err); + return err; + } } av_dump_format(fmt_ctx, 0, filename, 0); @@ -2705,35 +2968,45 @@ static int open_input_file(InputFile *ifile, const char *filename) ist->st = stream; - if (stream->codec->codec_id == AV_CODEC_ID_PROBE) { + if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) { av_log(NULL, AV_LOG_WARNING, "Failed to probe codec for input stream %d\n", stream->index); continue; } - codec = avcodec_find_decoder(stream->codec->codec_id); + codec = avcodec_find_decoder(stream->codecpar->codec_id); if (!codec) { av_log(NULL, AV_LOG_WARNING, "Unsupported codec with id %d for input stream %d\n", - stream->codec->codec_id, stream->index); + stream->codecpar->codec_id, stream->index); continue; } { - AVDictionary *opts = filter_codec_opts(codec_opts, stream->codec->codec_id, + AVDictionary *opts = filter_codec_opts(codec_opts, stream->codecpar->codec_id, fmt_ctx, stream, codec); ist->dec_ctx = avcodec_alloc_context3(codec); if (!ist->dec_ctx) exit(1); - //TODO:copy context - err = avcodec_copy_context(ist->dec_ctx, stream->codec); + err = avcodec_parameters_to_context(ist->dec_ctx, stream->codecpar); if (err < 0) exit(1); - av_codec_set_pkt_timebase(ist->dec_ctx, stream->time_base); + if (do_show_log) { + // For loging it is needed to disable at least frame threads as otherwise + // the log information would need to be reordered and matches up to contexts and frames + // That is in fact possible but not trivial + av_dict_set(&codec_opts, "threads", "1", 0); + } + + ist->dec_ctx->pkt_timebase = stream->time_base; ist->dec_ctx->framerate = stream->avg_frame_rate; +#if FF_API_LAVF_AVCTX + ist->dec_ctx->coded_width = stream->codec->coded_width; + ist->dec_ctx->coded_height = stream->codec->coded_height; +#endif if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) { av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n", @@ -2759,7 +3032,7 @@ static void close_input_file(InputFile *ifile) /* close decoder for each stream */ for (i = 0; i < ifile->nb_streams; i++) - if (ifile->streams[i].st->codec->codec_id != AV_CODEC_ID_NONE) + if (ifile->streams[i].st->codecpar->codec_id != AV_CODEC_ID_NONE) avcodec_free_context(&ifile->streams[i].dec_ctx); av_freep(&ifile->streams); @@ -2800,6 +3073,8 @@ static int probe_file(WriterContext *wctx, const char *filename) } else { selected_streams[i] = 1; } + if (!selected_streams[i]) + ifile.fmt_ctx->streams[i]->discard = AVDISCARD_ALL; } if (do_read_frames || do_read_packets) { @@ -2849,7 +3124,7 @@ end: static void show_usage(void) { av_log(NULL, AV_LOG_INFO, "Simple multimedia streams analyzer\n"); - av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", ffprobe_program_name); + av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", program_name); av_log(NULL, AV_LOG_INFO, "\n"); } @@ -2930,7 +3205,9 @@ static void ffprobe_show_pixel_formats(WriterContext *w) PRINT_PIX_FMT_FLAG(HWACCEL, "hwaccel"); PRINT_PIX_FMT_FLAG(PLANAR, "planar"); PRINT_PIX_FMT_FLAG(RGB, "rgb"); +#if FF_API_PSEUDOPAL PRINT_PIX_FMT_FLAG(PSEUDOPAL, "pseudopal"); +#endif PRINT_PIX_FMT_FLAG(ALPHA, "alpha"); writer_print_section_footer(w); } @@ -3086,6 +3363,7 @@ void show_ffprobe_help_default(const char *opt, const char *arg) printf("\n"); show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM); + show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM); } /** @@ -3158,6 +3436,7 @@ static int parse_read_interval(const char *interval_spec, } interval->end = lli; } else { + interval->duration_frames = 0; ret = av_parse_time(&us, p, 1); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Invalid interval end/duration specification '%s'\n", p); @@ -3291,7 +3570,7 @@ DEFINE_OPT_SHOW_SECTION(streams, STREAMS) DEFINE_OPT_SHOW_SECTION(programs, PROGRAMS) static const OptionDef real_options[] = { -#include "cmdutils_common_opts.h" + CMDUTILS_COMMON_OPTIONS { "f", HAS_ARG, {.func_arg = opt_format}, "force format", "format" }, { "unit", OPT_BOOL, {&show_value_unit}, "show unit of the displayed values" }, { "prefix", OPT_BOOL, {&use_value_prefix}, "use SI prefixes for the displayed values" }, @@ -3315,6 +3594,9 @@ static const OptionDef real_options[] = { "show a particular entry from the format/container info", "entry" }, { "show_entries", HAS_ARG, {.func_arg = opt_show_entries}, "show a set of specified entries", "entry_list" }, +#if HAVE_THREADS + { "show_log", OPT_INT|HAS_ARG, {(void*)&do_show_log}, "show log" }, +#endif { "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" }, { "show_programs", 0, {(void*)&opt_show_programs}, "show programs info" }, { "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" }, @@ -3331,6 +3613,8 @@ static const OptionDef real_options[] = { { "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" }, { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default}, "generic catch all option", "" }, { "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"}, + { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info }, + "read and decode the streams to fill missing information with heuristics" }, { NULL, }, }; @@ -3365,12 +3649,19 @@ char* ffprobe_run(int argc, char **argv) } memset(print_buffer, '\0', (size_t) buffer_size); + init_dynload(); + +#if HAVE_THREADS + ret = pthread_mutex_init(&log_mutex, NULL); + if (ret != 0) { + goto end; + } +#endif av_log_set_flags(AV_LOG_SKIP_REPEATED); register_exit(ffprobe_cleanup); options = real_options; parse_loglevel(argc, argv, options); - av_register_all(); avformat_network_init(); init_opts(); #if CONFIG_AVDEVICE @@ -3380,6 +3671,9 @@ char* ffprobe_run(int argc, char **argv) show_banner(argc, argv, options); parse_options(NULL, argc, argv, options, opt_input_file); + if (do_show_log) + av_log_set_callback(log_callback); + /* mark things to show, based on -show_entries */ SET_DO_SHOW(CHAPTERS, chapters); SET_DO_SHOW(ERROR, error); @@ -3470,7 +3764,7 @@ char* ffprobe_run(int argc, char **argv) (!do_show_program_version && !do_show_library_versions && !do_show_pixel_formats))) { show_usage(); av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n"); - av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", ffprobe_program_name); + av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name); ret = AVERROR(EINVAL); } else if (input_filename) { ret = probe_file(wctx, input_filename); @@ -3494,4 +3788,4 @@ end: avformat_network_deinit(); return print_buffer; -} \ No newline at end of file +}