Permalink
Cannot retrieve contributors at this time
Fetching contributors…

/* | |
* Various utilities for command line tools | |
* Copyright (c) 2000-2003 Fabrice Bellard | |
* | |
* This file is part of FFmpeg. | |
* | |
* FFmpeg is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
* License as published by the Free Software Foundation; either | |
* version 2.1 of the License, or (at your option) any later version. | |
* | |
* FFmpeg is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* You should have received a copy of the GNU Lesser General Public | |
* License along with FFmpeg; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
#include <string.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
#include <math.h> | |
#include "cmdutils.h" | |
/* Include only the enabled headers since some compilers (namely, Sun | |
Studio) will not omit unused inline functions and create undefined | |
references to libraries that are not being built. */ | |
#include <FFmpegDecoder/config.h> | |
#include <FFmpegDecoder/libavdevice/avdevice.h> | |
#include <FFmpegDecoder/libavutil/avstring.h> | |
#include <FFmpegDecoder/libavcodec/opt.h> | |
#include <FFmpegDecoder/libavutil/opt.h> | |
#include "cmdutils.h" | |
#include <FFmpegDecoder/libavcodec/version.h> | |
#undef exit | |
#undef exit | |
const char **opt_names; | |
static int opt_name_count; | |
AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB]; | |
AVFormatContext *avformat_opts; | |
struct SwsContext *sws_opts; | |
const int this_year = 2009; | |
double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max) | |
{ | |
char *tail; | |
const char *error; | |
double d = strtod(numstr, &tail); | |
if (*tail) | |
error= "Expected number for %s but found: %s\n"; | |
else if (d < min || d > max) | |
error= "The value for %s was %s which is not within %f - %f\n"; | |
else if(type == OPT_INT64 && (int64_t)d != d) | |
error= "Expected int64 for %s but found %s\n"; | |
else | |
return d; | |
//av_log(" ",stderr, error, context, numstr, min, max); | |
exit(1); | |
} | |
int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration) | |
{ | |
int64_t us = parse_date(timestr, is_duration); | |
if (us == INT64_MIN) { | |
//av_log(" ",stderr, "Invalid %s specification for %s: %s\n", | |
// is_duration ? "duration" : "date", context, timestr); | |
exit(1); | |
} | |
return us; | |
} | |
void show_help_options(const OptionDef *options, const char *msg, int mask, int value) | |
{ | |
const OptionDef *po; | |
int first; | |
first = 1; | |
for(po = options; po->name != NULL; po++) { | |
char buf[64]; | |
if ((po->flags & mask) == value) { | |
if (first) { | |
//av_log(" ","%s", msg); | |
first = 0; | |
} | |
av_strlcpy(buf, po->name, sizeof(buf)); | |
if (po->flags & HAS_ARG) { | |
av_strlcat(buf, " ", sizeof(buf)); | |
av_strlcat(buf, po->argname, sizeof(buf)); | |
} | |
//av_log(" ","-%-17s %s\n", buf, po->help); | |
} | |
} | |
} | |
static const OptionDef* find_option(const OptionDef *po, const char *name){ | |
while (po->name != NULL) { | |
if (!strcmp(name, po->name)) | |
break; | |
po++; | |
} | |
return po; | |
} | |
void parse_options(int argc, char **argv, const OptionDef *options, | |
void (* parse_arg_function)(const char*)) | |
{ | |
const char *opt, *arg; | |
int optindex, handleoptions=1; | |
const OptionDef *po; | |
/* parse options */ | |
optindex = 1; | |
while (optindex < argc) { | |
opt = argv[optindex++]; | |
if (handleoptions && opt[0] == '-' && opt[1] != '\0') { | |
if (opt[1] == '-' && opt[2] == '\0') { | |
handleoptions = 0; | |
continue; | |
} | |
po= find_option(options, opt + 1); | |
if (!po->name) | |
po= find_option(options, "default"); | |
if (!po->name) { | |
unknown_opt: | |
//av_log(" ",stderr, "%s: unrecognized option '%s'\n", argv[0], opt); | |
exit(1); | |
} | |
arg = NULL; | |
if (po->flags & HAS_ARG) { | |
arg = argv[optindex++]; | |
if (!arg) { | |
//av_log(" ",stderr, "%s: missing argument for option '%s'\n", argv[0], opt); | |
exit(1); | |
} | |
} | |
if (po->flags & OPT_STRING) { | |
char *str; | |
str = av_strdup(arg); | |
*po->u.str_arg = str; | |
} else if (po->flags & OPT_BOOL) { | |
*po->u.int_arg = 1; | |
} else if (po->flags & OPT_INT) { | |
*po->u.int_arg = parse_number_or_die(opt+1, arg, OPT_INT64, INT_MIN, INT_MAX); | |
} else if (po->flags & OPT_INT64) { | |
*po->u.int64_arg = parse_number_or_die(opt+1, arg, OPT_INT64, INT64_MIN, INT64_MAX); | |
} else if (po->flags & OPT_FLOAT) { | |
*po->u.float_arg = parse_number_or_die(opt+1, arg, OPT_FLOAT, -1.0/0.0, 1.0/0.0); | |
} else if (po->flags & OPT_FUNC2) { | |
if(po->u.func2_arg(opt+1, arg)<0) | |
goto unknown_opt; | |
} else { | |
po->u.func_arg(arg); | |
} | |
if(po->flags & OPT_EXIT) | |
exit(0); | |
} else { | |
if (parse_arg_function) | |
parse_arg_function(opt); | |
} | |
} | |
} | |
int opt_default(const char *opt, const char *arg){ | |
int type; | |
int ret= 0; | |
const AVOption *o= NULL; | |
int opt_types[]={AV_OPT_FLAG_VIDEO_PARAM, AV_OPT_FLAG_AUDIO_PARAM, 0, AV_OPT_FLAG_SUBTITLE_PARAM, 0}; | |
for(type=0; type<AVMEDIA_TYPE_NB && ret>= 0; type++){ | |
const AVOption *o2 = av_find_opt(avcodec_opts[0], opt, NULL, opt_types[type], opt_types[type]); | |
if(o2) | |
ret = av_set_string3(avcodec_opts[type], opt, arg, 1, &o); | |
} | |
if(!o) | |
ret = av_set_string3(avformat_opts, opt, arg, 1, &o); | |
if(!o) | |
ret = av_set_string3(sws_opts, opt, arg, 1, &o); | |
if(!o){ | |
if(opt[0] == 'a') | |
ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_AUDIO], opt+1, arg, 1, &o); | |
else if(opt[0] == 'v') | |
ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_VIDEO], opt+1, arg, 1, &o); | |
else if(opt[0] == 's') | |
ret = av_set_string3(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], opt+1, arg, 1, &o); | |
} | |
if (o && ret < 0) { | |
//av_log(" ",stderr, "Invalid value '%s' for option '%s'\n", arg, opt); | |
exit(1); | |
} | |
if(!o) | |
return -1; | |
// //av_log(NULL, //av_log_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avcodec_opts, opt, NULL), (int)av_get_int(avcodec_opts, opt, NULL)); | |
//FIXME we should always use avcodec_opts, ... for storing options so there will not be any need to keep track of what i set over this | |
opt_names= av_realloc(opt_names, sizeof(void*)*(opt_name_count+1)); | |
opt_names[opt_name_count++]= o->name; | |
if(avcodec_opts[0]->debug || avformat_opts->debug) | |
//av_log_set_level(//av_log_DEBUG); | |
return 0; | |
} | |
void set_context_opts(void *ctx, void *opts_ctx, int flags) | |
{ | |
int i; | |
for(i=0; i<opt_name_count; i++){ | |
char buf[256]; | |
const AVOption *opt; | |
const char *str= av_get_string(opts_ctx, opt_names[i], &opt, buf, sizeof(buf)); | |
/* if an option with name opt_names[i] is present in opts_ctx then str is non-NULL */ | |
if(str && ((opt->flags & flags) == flags)) | |
av_set_string3(ctx, opt_names[i], str, 1, NULL); | |
} | |
} | |
void print_error(const char *filename, int err) | |
{ | |
switch(err) { | |
case AVERROR_INVALIDDATA: | |
//av_log(" ",stderr, "%s: Error while parsing header\n", filename); | |
break; | |
case AVERROR(EIO): | |
//av_log(" ",stderr, "%s: I/O error occurred\n" | |
// "Usually that means that input file is truncated and/or corrupted.\n", | |
// filename); | |
break; | |
case AVERROR(ENOMEM): | |
//av_log(" ",stderr, "%s: memory allocation error occurred\n", filename); | |
break; | |
case AVERROR(ENOENT): | |
//av_log(" ",stderr, "%s: no such file or directory\n", filename); | |
break; | |
default: | |
//av_log(" ",stderr, "%s: Error while opening file\n", filename); | |
break; | |
} | |
} | |
#define PRINT_LIB_VERSION(outstream,libname,LIBNAME,indent) \ | |
version= libname##_version(); \ | |
//av_log(" ",outstream, "%slib%-10s %2d.%2d.%2d / %2d.%2d.%2d\n", indent? " " : "", #libname, \ | |
LIB##LIBNAME##_VERSION_MAJOR, LIB##LIBNAME##_VERSION_MINOR, LIB##LIBNAME##_VERSION_MICRO, \ | |
version >> 16, version >> 8 & 0xff, version & 0xff); | |
static void print_all_lib_versions(FILE* outstream, int indent) | |
{ | |
unsigned int version; | |
PRINT_LIB_VERSION(outstream, avutil, AVUTIL, indent); | |
PRINT_LIB_VERSION(outstream, avcodec, AVCODEC, indent); | |
PRINT_LIB_VERSION(outstream, avformat, AVFORMAT, indent); | |
PRINT_LIB_VERSION(outstream, avdevice, AVDEVICE, indent); | |
#if CONFIG_AVFILTER | |
PRINT_LIB_VERSION(outstream, avfilter, AVFILTER, indent); | |
#endif | |
PRINT_LIB_VERSION(outstream, swscale, SWSCALE, indent); | |
#if CONFIG_POSTPROC | |
PRINT_LIB_VERSION(outstream, postproc, POSTPROC, indent); | |
#endif | |
} | |
void show_banner(void) | |
{ | |
//av_log(" ",stderr, "%s version " FFMPEG_VERSION ", Copyright (c) %d-%d Fabrice Bellard, et al.\n", | |
// program_name, program_birth_year, this_year); | |
//av_log(" ",stderr, " configuration: " FFMPEG_CONFIGURATION "\n"); | |
print_all_lib_versions(stderr, 1); | |
//av_log(" ",stderr, " built on " __DATE__ " " __TIME__); | |
#ifdef __GNUC__ | |
//av_log(" ",stderr, ", gcc: " __VERSION__ "\n"); | |
#else | |
//av_log(" ",stderr, ", using a non-gcc compiler\n"); | |
#endif | |
} | |
void show_version(void) { | |
//av_log(" ","%s " FFMPEG_VERSION "\n", program_name); | |
print_all_lib_versions(stdout, 0); | |
} | |
void show_license(void) | |
{ | |
} | |
void show_formats(void) | |
{ | |
AVInputFormat *ifmt=NULL; | |
AVOutputFormat *ofmt=NULL; | |
URLProtocol *up=NULL; | |
AVCodec *p=NULL, *p2; | |
AVBitStreamFilter *bsf=NULL; | |
const char *last_name; | |
//av_log(" ","File formats:\n"); | |
last_name= "000"; | |
for(;;){ | |
int decode=0; | |
int encode=0; | |
const char *name=NULL; | |
const char *long_name=NULL; | |
while((ofmt= av_oformat_next(ofmt))) { | |
if((name == NULL || 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))) { | |
if((name == NULL || 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==NULL) | |
break; | |
last_name= name; | |
} | |
//av_log(" ","\n"); | |
//av_log(" ","Codecs:\n"); | |
last_name= "000"; | |
for(;;){ | |
int decode=0; | |
int encode=0; | |
int cap=0; | |
const char *type_str; | |
p2=NULL; | |
while((p= av_codec_next(p))) { | |
if((p2==NULL || strcmp(p->name, p2->name)<0) && | |
strcmp(p->name, last_name)>0){ | |
p2= p; | |
decode= encode= cap=0; | |
} | |
if(p2 && strcmp(p->name, p2->name)==0){ | |
if(p->decode) decode=1; | |
if(p->encode) encode=1; | |
cap |= p->capabilities; | |
} | |
} | |
if(p2==NULL) | |
break; | |
last_name= p2->name; | |
switch(p2->type) { | |
case AVMEDIA_TYPE_VIDEO: | |
type_str = "V"; | |
break; | |
case AVMEDIA_TYPE_AUDIO: | |
type_str = "A"; | |
break; | |
case AVMEDIA_TYPE_SUBTITLE: | |
type_str = "S"; | |
break; | |
default: | |
type_str = "?"; | |
break; | |
} | |
/* if(p2->decoder && decode==0) | |
//av_log(" "," use %s for decoding", p2->decoder->name);*/ | |
//av_log(" ","\n"); | |
} | |
//av_log(" ","\n"); | |
//av_log(" ","Bitstream filters:\n"); | |
while((bsf = av_bitstream_filter_next(bsf))) | |
//av_log(" "," %s", bsf->name); | |
//av_log(" ","\n"); | |
//av_log(" ","Supported file protocols:\n"); | |
while((up = av_protocol_next(up))) | |
//av_log(" "," %s:", up->name); | |
//av_log(" ","\n"); | |
//av_log(" ","Frame size, frame rate abbreviations:\n ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n"); | |
//av_log(" ","\n"); | |
(" ", | |
"Note, the names of encoders and decoders do not always match, so there are\n" | |
"several cases where the above table shows encoder only or decoder only entries\n" | |
"even though both encoding and decoding are supported. For example, the h263\n" | |
"decoder corresponds to the h263 and h263p encoders, for file formats it is even\n" | |
"worse.\n"); | |
} | |
int read_yesno(void) | |
{ | |
int c = getchar(); | |
int yesno = (toupper(c) == 'Y'); | |
while (c != '\n' && c != EOF) | |
c = getchar(); | |
return yesno; | |
} |