]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blobdiff - cmdutils.c
Fix segault
[frescor/ffmpeg.git] / cmdutils.c
index 46322e939daed6bb2108e87e4081226a80616ca4..167d15a71c9c517b02cd91aac72b39dec35bc713 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <math.h>
 
 
-#include "avformat.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 "config.h"
+#include "libavformat/avformat.h"
+#include "libavfilter/avfilter.h"
+#include "libavdevice/avdevice.h"
+#include "libswscale/swscale.h"
+#include "libpostproc/postprocess.h"
+#include "libavutil/avstring.h"
+#include "libavcodec/opt.h"
 #include "cmdutils.h"
 #include "cmdutils.h"
-#include "avstring.h"
 #include "version.h"
 #include "version.h"
-#include "config.h"
+#if CONFIG_NETWORK
+#include "libavformat/network.h"
+#endif
 
 #undef exit
 
 
 #undef exit
 
+const char **opt_names;
+static int opt_name_count;
+AVCodecContext *avcodec_opts[CODEC_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;
+    fprintf(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) {
+        fprintf(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;
 void show_help_options(const OptionDef *options, const char *msg, int mask, int value)
 {
     const OptionDef *po;
@@ -76,10 +125,10 @@ void parse_options(int argc, char **argv, const OptionDef *options,
         opt = argv[optindex++];
 
         if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
         opt = argv[optindex++];
 
         if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
-          if (opt[1] == '-' && opt[2] == '\0') {
-            handleoptions = 0;
-            continue;
-          }
+            if (opt[1] == '-' && opt[2] == '\0') {
+                handleoptions = 0;
+                continue;
+            }
             po= find_option(options, opt + 1);
             if (!po->name)
                 po= find_option(options, "default");
             po= find_option(options, opt + 1);
             if (!po->name)
                 po= find_option(options, "default");
@@ -103,17 +152,19 @@ unknown_opt:
             } else if (po->flags & OPT_BOOL) {
                 *po->u.int_arg = 1;
             } else if (po->flags & OPT_INT) {
             } else if (po->flags & OPT_BOOL) {
                 *po->u.int_arg = 1;
             } else if (po->flags & OPT_INT) {
-                *po->u.int_arg = atoi(arg);
+                *po->u.int_arg = parse_number_or_die(opt+1, arg, OPT_INT64, INT_MIN, INT_MAX);
             } else if (po->flags & OPT_INT64) {
             } else if (po->flags & OPT_INT64) {
-                *po->u.int64_arg = strtoll(arg, (char **)NULL, 10);
+                *po->u.int64_arg = parse_number_or_die(opt+1, arg, OPT_INT64, INT64_MIN, INT64_MAX);
             } else if (po->flags & OPT_FLOAT) {
             } else if (po->flags & OPT_FLOAT) {
-                *po->u.float_arg = atof(arg);
+                *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);
             }
             } 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);
         } else {
             if (parse_arg_function)
                 parse_arg_function(opt);
@@ -121,6 +172,60 @@ unknown_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<CODEC_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[CODEC_TYPE_AUDIO], opt+1, arg, 1, &o);
+        else if(opt[0] == 'v')
+            ret = av_set_string3(avcodec_opts[CODEC_TYPE_VIDEO], opt+1, arg, 1, &o);
+        else if(opt[0] == 's')
+            ret = av_set_string3(avcodec_opts[CODEC_TYPE_SUBTITLE], opt+1, arg, 1, &o);
+    }
+    if (o && ret < 0) {
+        fprintf(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) {
 void print_error(const char *filename, int err)
 {
     switch(err) {
@@ -138,30 +243,55 @@ void print_error(const char *filename, int err)
         fprintf(stderr, "%s: Unknown format\n", filename);
         break;
     case AVERROR(EIO):
         fprintf(stderr, "%s: Unknown format\n", filename);
         break;
     case AVERROR(EIO):
-        fprintf(stderr, "%s: I/O error occured\n"
+        fprintf(stderr, "%s: I/O error occurred\n"
                 "Usually that means that input file is truncated and/or corrupted.\n",
                 filename);
         break;
     case AVERROR(ENOMEM):
                 "Usually that means that input file is truncated and/or corrupted.\n",
                 filename);
         break;
     case AVERROR(ENOMEM):
-        fprintf(stderr, "%s: memory allocation error occured\n", filename);
+        fprintf(stderr, "%s: memory allocation error occurred\n", filename);
         break;
     case AVERROR(ENOENT):
         fprintf(stderr, "%s: no such file or directory\n", filename);
         break;
         break;
     case AVERROR(ENOENT):
         fprintf(stderr, "%s: no such file or directory\n", filename);
         break;
+#if CONFIG_NETWORK
+    case AVERROR(FF_NETERROR(EPROTONOSUPPORT)):
+        fprintf(stderr, "%s: Unsupported network protocol\n", filename);
+        break;
+#endif
     default:
         fprintf(stderr, "%s: Error while opening file\n", filename);
         break;
     }
 }
 
     default:
         fprintf(stderr, "%s: Error while opening file\n", filename);
         break;
     }
 }
 
-void show_banner(const char *program_name, int program_birth_year)
+#define PRINT_LIB_VERSION(outstream,libname,LIBNAME,indent) \
+    version= libname##_version(); \
+    fprintf(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)
 {
 {
-    fprintf(stderr, "%s version " FFMPEG_VERSION ", Copyright (c) %d-2008 Fabrice Bellard, et al.\n",
-            program_name, program_birth_year);
+    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)
+{
+    fprintf(stderr, "%s version " FFMPEG_VERSION ", Copyright (c) %d-%d Fabrice Bellard, et al.\n",
+            program_name, program_birth_year, this_year);
     fprintf(stderr, "  configuration: " FFMPEG_CONFIGURATION "\n");
     fprintf(stderr, "  configuration: " FFMPEG_CONFIGURATION "\n");
-    fprintf(stderr, "  libavutil version: " AV_STRINGIFY(LIBAVUTIL_VERSION) "\n");
-    fprintf(stderr, "  libavcodec version: " AV_STRINGIFY(LIBAVCODEC_VERSION) "\n");
-    fprintf(stderr, "  libavformat version: " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\n");
+    print_all_lib_versions(stderr, 1);
     fprintf(stderr, "  built on " __DATE__ " " __TIME__);
 #ifdef __GNUC__
     fprintf(stderr, ", gcc: " __VERSION__ "\n");
     fprintf(stderr, "  built on " __DATE__ " " __TIME__);
 #ifdef __GNUC__
     fprintf(stderr, ", gcc: " __VERSION__ "\n");
@@ -170,48 +300,186 @@ void show_banner(const char *program_name, int program_birth_year)
 #endif
 }
 
 #endif
 }
 
-void show_version(const char *program_name) {
-     /* TODO: add function interface to avutil and avformat */
+void show_version(void) {
     printf("%s " FFMPEG_VERSION "\n", program_name);
     printf("%s " FFMPEG_VERSION "\n", program_name);
-    printf("libavutil   %d\n"
-           "libavcodec  %d\n"
-           "libavformat %d\n",
-           LIBAVUTIL_BUILD, avcodec_build(), LIBAVFORMAT_BUILD);
+    print_all_lib_versions(stdout, 0);
 }
 
 void show_license(void)
 {
 }
 
 void show_license(void)
 {
-#ifdef CONFIG_GPL
+#if CONFIG_NONFREE
     printf(
     printf(
-    "FFmpeg is free software; you can redistribute it and/or modify\n"
+    "This version of %s has nonfree parts compiled in.\n"
+    "Therefore it is not legally redistributable.\n",
+    program_name
+    );
+#elif CONFIG_GPL
+    printf(
+    "%s is free software; you can redistribute it and/or modify\n"
     "it under the terms of the GNU General Public License as published by\n"
     "the Free Software Foundation; either version 2 of the License, or\n"
     "(at your option) any later version.\n"
     "\n"
     "it under the terms of the GNU General Public License as published by\n"
     "the Free Software Foundation; either version 2 of the License, or\n"
     "(at your option) any later version.\n"
     "\n"
-    "FFmpeg is distributed in the hope that it will be useful,\n"
+    "%s is distributed in the hope that it will be useful,\n"
     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
     "GNU General Public License for more details.\n"
     "\n"
     "You should have received a copy of the GNU General Public License\n"
     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
     "GNU General Public License for more details.\n"
     "\n"
     "You should have received a copy of the GNU General Public License\n"
-    "along with FFmpeg; if not, write to the Free Software\n"
-    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
+    "along with %s; if not, write to the Free Software\n"
+    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
+    program_name, program_name, program_name
     );
 #else
     printf(
     );
 #else
     printf(
-    "FFmpeg is free software; you can redistribute it and/or\n"
+    "%s is free software; you can redistribute it and/or\n"
     "modify it under the terms of the GNU Lesser General Public\n"
     "License as published by the Free Software Foundation; either\n"
     "version 2.1 of the License, or (at your option) any later version.\n"
     "\n"
     "modify it under the terms of the GNU Lesser General Public\n"
     "License as published by the Free Software Foundation; either\n"
     "version 2.1 of the License, or (at your option) any later version.\n"
     "\n"
-    "FFmpeg is distributed in the hope that it will be useful,\n"
+    "%s is distributed in the hope that it will be useful,\n"
     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
     "Lesser General Public License for more details.\n"
     "\n"
     "You should have received a copy of the GNU Lesser General Public\n"
     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
     "Lesser General Public License for more details.\n"
     "\n"
     "You should have received a copy of the GNU Lesser General Public\n"
-    "License along with FFmpeg; if not, write to the Free Software\n"
-    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
+    "License along with %s; if not, write to the Free Software\n"
+    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
+    program_name, program_name, program_name
     );
 #endif
 }
     );
 #endif
 }
+
+void show_formats(void)
+{
+    AVInputFormat *ifmt=NULL;
+    AVOutputFormat *ofmt=NULL;
+    URLProtocol *up=NULL;
+    AVCodec *p=NULL, *p2;
+    AVBitStreamFilter *bsf=NULL;
+    const char *last_name;
+
+    printf("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;
+
+        printf(
+            " %s%s %-15s %s\n",
+            decode ? "D":" ",
+            encode ? "E":" ",
+            name,
+            long_name ? long_name:" ");
+    }
+    printf("\n");
+
+    printf("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 CODEC_TYPE_VIDEO:
+            type_str = "V";
+            break;
+        case CODEC_TYPE_AUDIO:
+            type_str = "A";
+            break;
+        case CODEC_TYPE_SUBTITLE:
+            type_str = "S";
+            break;
+        default:
+            type_str = "?";
+            break;
+        }
+        printf(
+            " %s%s%s%s%s%s %-15s %s",
+            decode ? "D": (/*p2->decoder ? "d":*/" "),
+            encode ? "E":" ",
+            type_str,
+            cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ",
+            cap & CODEC_CAP_DR1 ? "D":" ",
+            cap & CODEC_CAP_TRUNCATED ? "T":" ",
+            p2->name,
+            p2->long_name ? p2->long_name : "");
+       /* if(p2->decoder && decode==0)
+            printf(" use %s for decoding", p2->decoder->name);*/
+        printf("\n");
+    }
+    printf("\n");
+
+    printf("Bitstream filters:\n");
+    while((bsf = av_bitstream_filter_next(bsf)))
+        printf(" %s", bsf->name);
+    printf("\n");
+
+    printf("Supported file protocols:\n");
+    while((up = av_protocol_next(up)))
+        printf(" %s:", up->name);
+    printf("\n");
+
+    printf("Frame size, frame rate abbreviations:\n ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n");
+    printf("\n");
+    printf(
+"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;
+}