*/
#include <string.h>
+#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/bprint.h"
+#include "libavutil/display.h"
#include "libavutil/mathematics.h"
#include "libavutil/imgutils.h"
+#include "libavutil/libm.h"
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/eval.h"
#include "libavutil/dict.h"
#include "libavutil/opt.h"
+#include "libavutil/cpu.h"
+#include "libavutil/ffversion.h"
+#include "libavutil/version.h"
#include "cmdutils.h"
-#include "version.h"
#if CONFIG_NETWORK
#include "libavformat/network.h"
#endif
#include <sys/time.h>
#include <sys/resource.h>
#endif
-#if CONFIG_OPENCL
-#include "libavutil/opencl.h"
-#endif
-
static int init_report(const char *env);
-struct SwsContext *sws_opts;
+AVDictionary *sws_dict;
AVDictionary *swr_opts;
AVDictionary *format_opts, *codec_opts, *resample_opts;
-const int this_year = 2013;
-
static FILE *report_file;
+static int report_file_level = AV_LOG_DEBUG;
+int hide_banner = 0;
void init_opts(void)
{
-
- if(CONFIG_SWSCALE)
- sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC,
- NULL, NULL, NULL);
+ av_dict_set(&sws_dict, "flags", "bicubic", 0);
}
void uninit_opts(void)
{
-#if CONFIG_SWSCALE
- sws_freeContext(sws_opts);
- sws_opts = NULL;
-#endif
-
av_dict_free(&swr_opts);
+ av_dict_free(&sws_dict);
av_dict_free(&format_opts);
av_dict_free(&codec_opts);
av_dict_free(&resample_opts);
av_log_default_callback(ptr, level, fmt, vl);
av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
va_end(vl2);
- fputs(line, report_file);
- fflush(report_file);
+ if (report_file_level >= level) {
+ fputs(line, report_file);
+ fflush(report_file);
+ }
+}
+
+static void (*program_exit)(int ret);
+
+void register_exit(void (*cb)(int ret))
+{
+ program_exit = cb;
+}
+
+void exit_program(int ret)
+{
+ if (program_exit)
+ program_exit(ret);
+
+ exit(ret);
}
double parse_number_or_die(const char *context, const char *numstr, int type,
else
return d;
av_log(NULL, AV_LOG_FATAL, error, context, numstr, min, max);
- exit(1);
+ exit_program(1);
return 0;
}
if (av_parse_time(&us, timestr, is_duration) < 0) {
av_log(NULL, AV_LOG_FATAL, "Invalid %s specification for %s: %s\n",
is_duration ? "duration" : "date", context, timestr);
- exit(1);
+ exit_program(1);
}
return us;
}
int first;
first = 1;
- for (po = options; po->name != NULL; po++) {
+ for (po = options; po->name; po++) {
char buf[64];
if (((po->flags & req_flags) != req_flags) ||
const char *p = strchr(name, ':');
int len = p ? p - name : strlen(name);
- while (po->name != NULL) {
+ while (po->name) {
if (!strncmp(name, po->name, len) && strlen(po->name) == len)
break;
po++;
return po;
}
-#if HAVE_COMMANDLINETOARGVW
+/* _WIN32 means using the windows libc - cygwin doesn't define that
+ * 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 <windows.h>
#include <shellapi.h>
/* Will be leaked on exit */
win32_argv_utf8 = av_mallocz(sizeof(char *) * (win32_argc + 1) + buffsize);
argstr_flat = (char *)win32_argv_utf8 + sizeof(char *) * (win32_argc + 1);
- if (win32_argv_utf8 == NULL) {
+ if (!win32_argv_utf8) {
LocalFree(argv_w);
return;
}
if (po->flags & OPT_SPEC) {
SpecifierOpt **so = dst;
char *p = strchr(opt, ':');
+ char *str;
dstcount = (int *)(so + 1);
*so = grow_array(*so, sizeof(**so), dstcount, *dstcount + 1);
- (*so)[*dstcount - 1].specifier = av_strdup(p ? p + 1 : "");
+ str = av_strdup(p ? p + 1 : "");
+ if (!str)
+ return AVERROR(ENOMEM);
+ (*so)[*dstcount - 1].specifier = str;
dst = &(*so)[*dstcount - 1].u;
}
char *str;
str = av_strdup(arg);
av_freep(dst);
+ if (!str)
+ return AVERROR(ENOMEM);
*(char **)dst = str;
} else if (po->flags & OPT_BOOL || po->flags & OPT_INT) {
*(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
}
}
if (po->flags & OPT_EXIT)
- exit(0);
+ exit_program(0);
return 0;
}
opt++;
if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
- exit(1);
+ exit_program(1);
optindex += ret;
} else {
if (parse_arg_function)
(po->name && !strcmp(optname, po->name)))
return i;
- if (po->flags & HAS_ARG)
+ if (!po->name || po->flags & HAS_ARG)
i++;
}
return 0;
fputc('"', report_file);
}
+static void check_options(const OptionDef *po)
+{
+ while (po->name) {
+ if (po->flags & OPT_PERFILE)
+ av_assert0(po->flags & (OPT_INPUT | OPT_OUTPUT));
+ po++;
+ }
+}
+
void parse_loglevel(int argc, char **argv, const OptionDef *options)
{
int idx = locate_option(argc, argv, options, "loglevel");
const char *env;
+
+ check_options(options);
+
if (!idx)
idx = locate_option(argc, argv, options, "v");
if (idx && argv[idx + 1])
fflush(report_file);
}
}
+ idx = locate_option(argc, argv, options, "hide_banner");
+ if (idx)
+ hide_banner = 1;
+}
+
+static const AVOption *opt_find(void *obj, const char *name, const char *unit,
+ int opt_flags, int search_flags)
+{
+ const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags);
+ if(o && !o->flags)
+ return NULL;
+ return o;
}
-#define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
+#define FLAGS (o->type == AV_OPT_TYPE_FLAGS && (arg[0]=='-' || arg[0]=='+')) ? AV_DICT_APPEND : 0
int opt_default(void *optctx, const char *opt, const char *arg)
{
const AVOption *o;
#if CONFIG_AVRESAMPLE
const AVClass *rc = avresample_get_class();
#endif
- const AVClass *sc, *swr_class;
+#if CONFIG_SWSCALE
+ const AVClass *sc = sws_get_class();
+#endif
+#if CONFIG_SWRESAMPLE
+ const AVClass *swr_class = swr_get_class();
+#endif
if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug"))
av_log_set_level(AV_LOG_DEBUG);
p = opt + strlen(opt);
av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1));
- if ((o = av_opt_find(&cc, opt_stripped, NULL, 0,
+ if ((o = opt_find(&cc, opt_stripped, NULL, 0,
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) ||
((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&
- (o = av_opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) {
+ (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) {
av_dict_set(&codec_opts, opt, arg, FLAGS);
consumed = 1;
}
- if ((o = av_opt_find(&fc, opt, NULL, 0,
+ if ((o = opt_find(&fc, opt, NULL, 0,
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
av_dict_set(&format_opts, opt, arg, FLAGS);
if (consumed)
consumed = 1;
}
#if CONFIG_SWSCALE
- sc = sws_get_class();
- if (!consumed && av_opt_find(&sc, opt, NULL, 0,
- AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) {
- // XXX we only support sws_flags, not arbitrary sws options
- int ret = av_opt_set(sws_opts, opt, arg, 0);
+ if (!consumed && (o = opt_find(&sc, opt, NULL, 0,
+ AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
+ struct SwsContext *sws = sws_alloc_context();
+ int ret = av_opt_set(sws, opt, arg, 0);
+ sws_freeContext(sws);
+ if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") ||
+ !strcmp(opt, "dstw") || !strcmp(opt, "dsth") ||
+ !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) {
+ av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n");
+ return AVERROR(EINVAL);
+ }
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt);
return ret;
}
+
+ av_dict_set(&sws_dict, opt, arg, FLAGS);
+
+ consumed = 1;
+ }
+#else
+ if (!consumed && !strcmp(opt, "sws_flags")) {
+ av_log(NULL, AV_LOG_WARNING, "Ignoring %s %s, due to disabled swscale\n", opt, arg);
consumed = 1;
}
#endif
#if CONFIG_SWRESAMPLE
- swr_class = swr_get_class();
- if (!consumed && (o=av_opt_find(&swr_class, opt, NULL, 0,
+ if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0,
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
struct SwrContext *swr = swr_alloc();
int ret = av_opt_set(swr, opt, arg, 0);
}
#endif
#if CONFIG_AVRESAMPLE
- if ((o=av_opt_find(&rc, opt, NULL, 0,
+ if ((o=opt_find(&rc, opt, NULL, 0,
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {
av_dict_set(&resample_opts, opt, arg, FLAGS);
consumed = 1;
*g = octx->cur_group;
g->arg = arg;
g->group_def = l->group_def;
-#if CONFIG_SWSCALE
- g->sws_opts = sws_opts;
-#endif
+ g->sws_dict = sws_dict;
g->swr_opts = swr_opts;
g->codec_opts = codec_opts;
g->format_opts = format_opts;
codec_opts = NULL;
format_opts = NULL;
resample_opts = NULL;
-#if CONFIG_SWSCALE
- sws_opts = NULL;
-#endif
+ sws_dict = NULL;
swr_opts = NULL;
init_opts();
memset(octx, 0, sizeof(*octx));
octx->nb_groups = nb_groups;
- octx->groups = av_mallocz(sizeof(*octx->groups) * octx->nb_groups);
+ octx->groups = av_mallocz_array(octx->nb_groups, sizeof(*octx->groups));
if (!octx->groups)
- exit(1);
+ exit_program(1);
for (i = 0; i < octx->nb_groups; i++)
octx->groups[i].group_def = &groups[i];
av_dict_free(&l->groups[j].codec_opts);
av_dict_free(&l->groups[j].format_opts);
av_dict_free(&l->groups[j].resample_opts);
-#if CONFIG_SWSCALE
- sws_freeContext(l->groups[j].sws_opts);
-#endif
+
+ av_dict_free(&l->groups[j].sws_dict);
av_dict_free(&l->groups[j].swr_opts);
}
av_freep(&l->groups);
return 0;
}
+int opt_cpuflags(void *optctx, const char *opt, const char *arg)
+{
+ int ret;
+ unsigned flags = av_get_cpu_flags();
+
+ if ((ret = av_parse_cpu_caps(&flags, arg)) < 0)
+ return ret;
+
+ av_force_cpu_flags(flags);
+ return 0;
+}
+
int opt_loglevel(void *optctx, const char *opt, const char *arg)
{
const struct { const char *name; int level; } log_levels[] = {
{ "info" , AV_LOG_INFO },
{ "verbose", AV_LOG_VERBOSE },
{ "debug" , AV_LOG_DEBUG },
+ { "trace" , AV_LOG_TRACE },
};
char *tail;
int level;
+ int flags;
int i;
+ flags = av_log_get_flags();
tail = strstr(arg, "repeat");
- av_log_set_flags(tail ? 0 : AV_LOG_SKIP_REPEATED);
+ 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)
"Possible levels are numbers or:\n", arg);
for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++)
av_log(NULL, AV_LOG_FATAL, "\"%s\"\n", log_levels[i].name);
- exit(1);
+ exit_program(1);
}
av_log_set_level(level);
return 0;
av_free(filename_template);
filename_template = val;
val = NULL;
+ } else if (!strcmp(key, "level")) {
+ char *tail;
+ report_file_level = strtol(val, &tail, 10);
+ if (*tail) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n");
+ exit_program(1);
+ }
} else {
av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key);
}
report_file = fopen(filename.str, "w");
if (!report_file) {
+ int ret = AVERROR(errno);
av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
filename.str, strerror(errno));
- return AVERROR(errno);
+ return ret;
}
av_log_set_callback(log_callback_report);
av_log(NULL, AV_LOG_INFO,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
filename.str);
- av_log_set_level(FFMAX(av_log_get_level(), AV_LOG_VERBOSE));
av_bprint_finalize(&filename, NULL);
return 0;
}
max = strtol(arg, &tail, 10);
if (*tail) {
av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg);
- exit(1);
+ exit_program(1);
}
av_max_alloc(max);
return 0;
}
-int opt_cpuflags(void *optctx, const char *opt, const char *arg)
-{
- int ret;
- unsigned flags = av_get_cpu_flags();
-
- if ((ret = av_parse_cpu_caps(&flags, arg)) < 0)
- return ret;
-
- av_force_cpu_flags(flags);
- return 0;
-}
-
int opt_timelimit(void *optctx, const char *opt, const char *arg)
{
#if HAVE_SETRLIMIT
return 0;
}
-#if CONFIG_OPENCL
-int opt_opencl(void *optctx, const char *opt, const char *arg)
-{
- char *key, *value;
- const char *opts = arg;
- int ret = 0;
- while (*opts) {
- ret = av_opt_get_key_value(&opts, "=", ":", 0, &key, &value);
- if (ret < 0)
- return ret;
- ret = av_opencl_set_option(key, value);
- if (ret < 0)
- return ret;
- if (*opts)
- opts++;
- }
- return ret;
-}
-#endif
-
void print_error(const char *filename, int err)
{
char errbuf[128];
LIB##LIBNAME##_VERSION_MAJOR, \
LIB##LIBNAME##_VERSION_MINOR, \
LIB##LIBNAME##_VERSION_MICRO, \
- version >> 16, version >> 8 & 0xff, version & 0xff); \
+ AV_VERSION_MAJOR(version), AV_VERSION_MINOR(version),\
+ AV_VERSION_MICRO(version)); \
} \
if (flags & SHOW_CONFIG) { \
const char *cfg = libname##_configuration(); \
static void print_all_libs_info(int flags, int level)
{
- PRINT_LIB_INFO(avutil, AVUTIL, flags, level);
- PRINT_LIB_INFO(avcodec, AVCODEC, flags, level);
- PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
- PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
- PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
+ PRINT_LIB_INFO(avutil, AVUTIL, flags, level);
+ PRINT_LIB_INFO(avcodec, AVCODEC, flags, level);
+ PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
+ PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
+ PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
- PRINT_LIB_INFO(swscale, SWSCALE, flags, level);
- PRINT_LIB_INFO(swresample,SWRESAMPLE, flags, level);
- PRINT_LIB_INFO(postproc, POSTPROC, 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)
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, this_year);
+ program_birth_year, CONFIG_THIS_YEAR);
av_log(NULL, level, "\n");
- av_log(NULL, level, "%sbuilt on %s %s with %s\n",
- indent, __DATE__, __TIME__, CC_IDENT);
+ 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)
+{
+ const char *indent = flags & INDENT ? " " : "";
+ char str[] = { FFMPEG_CONFIGURATION };
+ char *conflist, *remove_tilde, *splitconf;
+
+ // Change all the ' --' strings to '~--' so that
+ // they can be identified as tokens.
+ while ((conflist = strstr(str, " --")) != NULL) {
+ strncpy(conflist, "~--", 3);
+ }
+
+ // Compensate for the weirdness this would cause
+ // when passing 'pkg-config --static'.
+ while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) {
+ strncpy(remove_tilde, "pkg-config ", 11);
+ }
+
+ splitconf = strtok(str, "~");
+ av_log(NULL, level, "\n%sconfiguration:\n", indent);
+ while (splitconf != NULL) {
+ av_log(NULL, level, "%s%s%s\n", indent, indent, splitconf);
+ splitconf = strtok(NULL, "~");
+ }
+}
+
void show_banner(int argc, char **argv, const OptionDef *options)
{
int idx = locate_option(argc, argv, options, "version");
- if (idx)
+ if (hide_banner || idx)
return;
print_program_info (INDENT|SHOW_COPYRIGHT, AV_LOG_INFO);
int show_version(void *optctx, const char *opt, const char *arg)
{
av_log_set_callback(log_callback_help);
- print_program_info (0 , AV_LOG_INFO);
+ print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO);
print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
return 0;
}
+int show_buildconf(void *optctx, const char *opt, const char *arg)
+{
+ av_log_set_callback(log_callback_help);
+ print_buildconf (INDENT|0, AV_LOG_INFO);
+
+ return 0;
+}
+
int show_license(void *optctx, const char *opt, const char *arg)
{
#if CONFIG_NONFREE
return 0;
}
-int show_formats(void *optctx, const char *opt, const char *arg)
+static int is_device(const AVClass *avclass)
+{
+ if (!avclass)
+ return 0;
+ 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)
{
AVInputFormat *ifmt = NULL;
AVOutputFormat *ofmt = NULL;
const char *last_name;
+ int is_dev;
- printf("File formats:\n"
+ printf("%s\n"
" D. = Demuxing supported\n"
" .E = Muxing supported\n"
- " --\n");
+ " --\n", device_only ? "Devices:" : "File formats:");
last_name = "000";
for (;;) {
int decode = 0;
const char *long_name = NULL;
while ((ofmt = av_oformat_next(ofmt))) {
- if ((name == NULL || strcmp(ofmt->name, name) < 0) &&
+ 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;
}
}
while ((ifmt = av_iformat_next(ifmt))) {
- if ((name == NULL || strcmp(ifmt->name, name) < 0) &&
+ 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;
if (name && strcmp(ifmt->name, name) == 0)
decode = 1;
}
- if (name == NULL)
+ if (!name)
break;
last_name = name;
return 0;
}
+int show_formats(void *optctx, const char *opt, const char *arg)
+{
+ return show_formats_devices(optctx, opt, arg, 0);
+}
+
+int show_devices(void *optctx, const char *opt, const char *arg)
+{
+ return show_formats_devices(optctx, opt, arg, 1);
+}
+
#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \
if (codec->field) { \
const type *p = codec->field; \
printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
c->long_name ? c->long_name : "");
+ printf(" General capabilities: ");
+ if (c->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)
+ printf("horizband ");
+ if (c->capabilities & AV_CODEC_CAP_DR1)
+ printf("dr1 ");
+ if (c->capabilities & AV_CODEC_CAP_TRUNCATED)
+ printf("trunc ");
+ if (c->capabilities & AV_CODEC_CAP_DELAY)
+ printf("delay ");
+ if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)
+ printf("small ");
+ if (c->capabilities & AV_CODEC_CAP_SUBFRAMES)
+ printf("subframes ");
+ if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL)
+ printf("exp ");
+ if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF)
+ printf("chconf ");
+ if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE)
+ printf("paramchange ");
+ if (c->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
+ printf("variable ");
+ if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS |
+ AV_CODEC_CAP_SLICE_THREADS |
+ AV_CODEC_CAP_AUTO_THREADS))
+ printf("threads ");
+ if (!c->capabilities)
+ printf("none");
+ printf("\n");
+
if (c->type == AVMEDIA_TYPE_VIDEO ||
c->type == AVMEDIA_TYPE_AUDIO) {
printf(" Threading capabilities: ");
- switch (c->capabilities & (CODEC_CAP_FRAME_THREADS |
- CODEC_CAP_SLICE_THREADS)) {
- case CODEC_CAP_FRAME_THREADS |
- CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break;
- case CODEC_CAP_FRAME_THREADS: printf("frame"); break;
- case CODEC_CAP_SLICE_THREADS: printf("slice"); break;
- default: printf("no"); break;
+ switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS |
+ AV_CODEC_CAP_SLICE_THREADS |
+ AV_CODEC_CAP_AUTO_THREADS)) {
+ case AV_CODEC_CAP_FRAME_THREADS |
+ AV_CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break;
+ case AV_CODEC_CAP_FRAME_THREADS: printf("frame"); break;
+ case AV_CODEC_CAP_SLICE_THREADS: printf("slice"); break;
+ case AV_CODEC_CAP_AUTO_THREADS : printf("auto"); break;
+ default: printf("none"); break;
}
printf("\n");
}
const AVCodecDescriptor * const *da = a;
const AVCodecDescriptor * const *db = b;
- return (*da)->type != (*db)->type ? (*da)->type - (*db)->type :
+ return (*da)->type != (*db)->type ? FFDIFFSIGN((*da)->type, (*db)->type) :
strcmp((*da)->name, (*db)->name);
}
nb_codecs++;
if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) {
av_log(NULL, AV_LOG_ERROR, "Out of memory\n");
- exit(1);
+ exit_program(1);
}
desc = NULL;
while ((desc = avcodec_descriptor_next(desc)))
const AVCodecDescriptor *desc = codecs[i];
const AVCodec *codec = NULL;
+ if (strstr(desc->name, "_deprecated"))
+ continue;
+
printf(" ");
printf(avcodec_find_decoder(desc->id) ? "D" : ".");
printf(avcodec_find_encoder(desc->id) ? "E" : ".");
while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
printf(" %c", get_media_type_char(desc->type));
- printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : ".");
- printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : ".");
- printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL) ? "X" : ".");
- printf((codec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");
- printf((codec->capabilities & CODEC_CAP_DR1) ? "D" : ".");
+ printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");
+ printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");
+ printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : ".");
+ printf((codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");
+ printf((codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : ".");
printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
if (strcmp(codec->name, desc->name))
printf("Supported file protocols:\n"
"Input:\n");
while ((name = avio_enum_protocols(&opaque, 0)))
- printf("%s\n", name);
+ printf(" %s\n", name);
printf("Output:\n");
while ((name = avio_enum_protocols(&opaque, 1)))
- printf("%s\n", name);
+ printf(" %s\n", name);
return 0;
}
int show_filters(void *optctx, const char *opt, const char *arg)
{
- const AVFilter av_unused(*filter) = NULL;
+#if CONFIG_AVFILTER
+ const AVFilter *filter = NULL;
char descr[64], *descr_cur;
int i, j;
const AVFilterPad *pad;
printf("Filters:\n"
- " T. = Timeline support\n"
- " .S = Slice threading\n"
+ " T.. = Timeline support\n"
+ " .S. = Slice threading\n"
+ " ..C = Command support\n"
" A = Audio input/output\n"
" V = Video input/output\n"
" N = Dynamic number and/or type of input/output\n"
" | = Source or sink filter\n");
-#if CONFIG_AVFILTER
while ((filter = avfilter_next(filter))) {
descr_cur = descr;
for (i = 0; i < 2; i++) {
*(descr_cur++) = '>';
}
pad = i ? filter->outputs : filter->inputs;
- for (j = 0; pad && pad[j].name; j++) {
+ for (j = 0; pad && avfilter_pad_get_name(pad, j); j++) {
if (descr_cur >= descr + sizeof(descr) - 4)
break;
- *(descr_cur++) = get_media_type_char(pad[j].type);
+ *(descr_cur++) = get_media_type_char(avfilter_pad_get_type(pad, j));
}
if (!j)
*(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) ||
( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|';
}
*descr_cur = 0;
- printf(" %c%c %-16s %-10s %s\n",
+ printf(" %c%c%c %-17s %-10s %s\n",
filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.',
filter->flags & AVFILTER_FLAG_SLICE_THREADS ? 'S' : '.',
+ filter->process_command ? 'C' : '.',
filter->name, descr, filter->description);
}
+#else
+ printf("No filters available: libavfilter disabled\n");
#endif
return 0;
}
+int show_colors(void *optctx, const char *opt, const char *arg)
+{
+ const char *name;
+ const uint8_t *rgb;
+ int i;
+
+ printf("%-32s #RRGGBB\n", "name");
+
+ for (i = 0; name = av_get_known_color_name(i, &rgb); i++)
+ printf("%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]);
+
+ return 0;
+}
+
int show_pix_fmts(void *optctx, const char *opt, const char *arg)
{
const AVPixFmtDescriptor *pix_desc = NULL;
const char *name, *descr;
printf("Individual channels:\n"
- "NAME DESCRIPTION\n");
+ "NAME DESCRIPTION\n");
for (i = 0; i < 63; i++) {
name = av_get_channel_name((uint64_t)1 << i);
if (!name)
continue;
descr = av_get_channel_description((uint64_t)1 << i);
- printf("%-12s%s\n", name, descr);
+ printf("%-14s %s\n", name, descr);
}
printf("\nStandard channel layouts:\n"
- "NAME DECOMPOSITION\n");
+ "NAME DECOMPOSITION\n");
for (i = 0; !av_get_standard_channel_layout(i, &layout, &name); i++) {
if (name) {
- printf("%-12s", name);
+ printf("%-14s ", name);
for (j = 1; j; j <<= 1)
if ((layout & j))
printf("%s%s", (layout & (j - 1)) ? "+" : "", av_get_channel_name(j));
av_log_set_callback(log_callback_help);
topic = av_strdup(arg ? arg : "");
+ if (!topic)
+ return AVERROR(ENOMEM);
par = strchr(topic, '=');
if (par)
*par++ = 0;
return yesno;
}
-int cmdutils_read_file(const char *filename, char **bufptr, size_t *size)
-{
- int ret;
- FILE *f = fopen(filename, "rb");
-
- if (!f) {
- av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename,
- strerror(errno));
- return AVERROR(errno);
- }
- fseek(f, 0, SEEK_END);
- *size = ftell(f);
- fseek(f, 0, SEEK_SET);
- if (*size == (size_t)-1) {
- av_log(NULL, AV_LOG_ERROR, "IO error: %s\n", strerror(errno));
- fclose(f);
- return AVERROR(errno);
- }
- *bufptr = av_malloc(*size + 1);
- if (!*bufptr) {
- av_log(NULL, AV_LOG_ERROR, "Could not allocate file buffer\n");
- fclose(f);
- return AVERROR(ENOMEM);
- }
- ret = fread(*bufptr, 1, *size, f);
- if (ret < *size) {
- av_free(*bufptr);
- if (ferror(f)) {
- av_log(NULL, AV_LOG_ERROR, "Error while reading file '%s': %s\n",
- filename, strerror(errno));
- ret = AVERROR(errno);
- } else
- ret = AVERROR_EOF;
- } else {
- ret = 0;
- (*bufptr)[(*size)++] = '\0';
- }
-
- fclose(f);
- return ret;
-}
-
FILE *get_preset_file(char *filename, size_t filename_size,
const char *preset_name, int is_path,
const char *codec_name)
switch (check_stream_specifier(s, st, p + 1)) {
case 1: *p = 0; break;
case 0: continue;
- default: return NULL;
+ default: exit_program(1);
}
if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
- (codec && codec->priv_class &&
+ !codec ||
+ (codec->priv_class &&
av_opt_find(&codec->priv_class, t->key, NULL, flags,
AV_OPT_SEARCH_FAKE_OBJ)))
av_dict_set(&ret, t->key, t->value, 0);
if (!s->nb_streams)
return NULL;
- opts = av_mallocz(s->nb_streams * sizeof(*opts));
+ opts = av_mallocz_array(s->nb_streams, sizeof(*opts));
if (!opts) {
av_log(NULL, AV_LOG_ERROR,
"Could not alloc memory for stream options.\n");
{
if (new_size >= INT_MAX / elem_size) {
av_log(NULL, AV_LOG_ERROR, "Array too big.\n");
- exit(1);
+ exit_program(1);
}
if (*size < new_size) {
- uint8_t *tmp = av_realloc(array, new_size*elem_size);
+ uint8_t *tmp = av_realloc_array(array, new_size, elem_size);
if (!tmp) {
av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n");
- exit(1);
+ exit_program(1);
}
memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
*size = new_size;
}
return array;
}
+
+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)
+ theta = -av_display_rotation_get((int32_t*) displaymatrix);
+
+ theta -= 360*floor(theta/360 + 0.9/360);
+
+ if (fabs(theta - 90*round(theta/90)) > 2)
+ av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\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)");
+
+ return theta;
+}
+
+#if CONFIG_AVDEVICE
+static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts)
+{
+ int ret, i;
+ AVDeviceInfoList *device_list = NULL;
+
+ 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);
+ if (!fmt->get_device_list) {
+ ret = AVERROR(ENOSYS);
+ printf("Cannot list sources. Not implemented.\n");
+ goto fail;
+ }
+
+ if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) {
+ printf("Cannot list sources.\n");
+ goto fail;
+ }
+
+ for (i = 0; i < device_list->nb_devices; i++) {
+ printf("%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
+ device_list->devices[i]->device_name, device_list->devices[i]->device_description);
+ }
+
+ fail:
+ avdevice_free_list_devices(&device_list);
+ return ret;
+}
+
+static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts)
+{
+ int ret, i;
+ AVDeviceInfoList *device_list = NULL;
+
+ 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);
+ if (!fmt->get_device_list) {
+ ret = AVERROR(ENOSYS);
+ printf("Cannot list sinks. Not implemented.\n");
+ goto fail;
+ }
+
+ if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) {
+ printf("Cannot list sinks.\n");
+ goto fail;
+ }
+
+ for (i = 0; i < device_list->nb_devices; i++) {
+ printf("%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
+ device_list->devices[i]->device_name, device_list->devices[i]->device_description);
+ }
+
+ fail:
+ avdevice_free_list_devices(&device_list);
+ return ret;
+}
+
+static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionary **opts)
+{
+ int ret;
+ if (arg) {
+ char *opts_str = NULL;
+ av_assert0(dev && opts);
+ *dev = av_strdup(arg);
+ if (!*dev)
+ return AVERROR(ENOMEM);
+ if ((opts_str = strchr(*dev, ','))) {
+ *(opts_str++) = '\0';
+ if (opts_str[0] && ((ret = av_dict_parse_string(opts, opts_str, "=", ":", 0)) < 0)) {
+ av_freep(dev);
+ return ret;
+ }
+ }
+ } else
+ printf("\nDevice name is not provided.\n"
+ "You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.\n\n");
+ return 0;
+}
+
+int show_sources(void *optctx, const char *opt, const char *arg)
+{
+ AVInputFormat *fmt = NULL;
+ char *dev = NULL;
+ AVDictionary *opts = NULL;
+ int ret = 0;
+ int error_level = av_log_get_level();
+
+ av_log_set_level(AV_LOG_ERROR);
+
+ if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
+ goto fail;
+
+ do {
+ fmt = av_input_audio_device_next(fmt);
+ if (fmt) {
+ if (!strcmp(fmt->name, "lavfi"))
+ continue; //it's pointless to probe lavfi
+ if (dev && !av_match_name(dev, fmt->name))
+ continue;
+ print_device_sources(fmt, opts);
+ }
+ } while (fmt);
+ do {
+ fmt = av_input_video_device_next(fmt);
+ if (fmt) {
+ if (dev && !av_match_name(dev, fmt->name))
+ continue;
+ print_device_sources(fmt, opts);
+ }
+ } while (fmt);
+ fail:
+ av_dict_free(&opts);
+ av_free(dev);
+ av_log_set_level(error_level);
+ return ret;
+}
+
+int show_sinks(void *optctx, const char *opt, const char *arg)
+{
+ AVOutputFormat *fmt = NULL;
+ char *dev = NULL;
+ AVDictionary *opts = NULL;
+ int ret = 0;
+ int error_level = av_log_get_level();
+
+ av_log_set_level(AV_LOG_ERROR);
+
+ if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
+ goto fail;
+
+ do {
+ fmt = av_output_audio_device_next(fmt);
+ if (fmt) {
+ if (dev && !av_match_name(dev, fmt->name))
+ continue;
+ print_device_sinks(fmt, opts);
+ }
+ } while (fmt);
+ do {
+ fmt = av_output_video_device_next(fmt);
+ if (fmt) {
+ if (dev && !av_match_name(dev, fmt->name))
+ continue;
+ print_device_sinks(fmt, opts);
+ }
+ } while (fmt);
+ fail:
+ av_dict_free(&opts);
+ av_free(dev);
+ av_log_set_level(error_level);
+ return ret;
+}
+
+#endif