X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmdutils.c;h=3dbb722d21a4aafb2f1d13f853a089720a289d21;hb=bcd0a7137e4aca0f6f598593b90ca8f338444c51;hp=6576eba95cc3bd3166d18fb7513780c9e30dabfe;hpb=f9fada2704df7994e8e4451ac78d8d5569faa8a2;p=ffmpeg diff --git a/cmdutils.c b/cmdutils.c index 6576eba95cc..3dbb722d21a 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -49,13 +49,14 @@ #include "libavformat/network.h" #endif #if HAVE_SYS_RESOURCE_H +#include #include #endif struct SwsContext *sws_opts; -AVDictionary *format_opts, *codec_opts; +AVDictionary *format_opts, *codec_opts, *resample_opts; -static const int this_year = 2012; +static const int this_year = 2013; void init_opts(void) { @@ -73,6 +74,7 @@ void uninit_opts(void) #endif av_dict_free(&format_opts); av_dict_free(&codec_opts); + av_dict_free(&resample_opts); } void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) @@ -97,7 +99,7 @@ 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_program(1); + exit(1); return 0; } @@ -108,7 +110,7 @@ int64_t parse_time_or_die(const char *context, const char *timestr, 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_program(1); + exit(1); } return us; } @@ -165,7 +167,7 @@ static const OptionDef *find_option(const OptionDef *po, const char *name) return po; } -#if defined(_WIN32) && !defined(__MINGW32CE__) +#if HAVE_COMMANDLINETOARGVW #include #include /* Will be leaked on exit */ @@ -225,38 +227,16 @@ static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr) { /* nothing to do */ } -#endif /* WIN32 && !__MINGW32CE__ */ +#endif /* HAVE_COMMANDLINETOARGVW */ -int parse_option(void *optctx, const char *opt, const char *arg, - const OptionDef *options) +static int write_option(void *optctx, const OptionDef *po, const char *opt, + const char *arg) { - const OptionDef *po; - int bool_val = 1; - int *dstcount; - void *dst; - - po = find_option(options, opt); - if (!po->name && opt[0] == 'n' && opt[1] == 'o') { - /* handle 'no' bool option */ - po = find_option(options, opt + 2); - if ((po->name && (po->flags & OPT_BOOL))) - bool_val = 0; - } - if (!po->name) - po = find_option(options, "default"); - if (!po->name) { - av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); - return AVERROR(EINVAL); - } - if (po->flags & HAS_ARG && !arg) { - av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); - return AVERROR(EINVAL); - } - /* new-style options contain an offset into optctx, old-style address of * a global var*/ - dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? (uint8_t *)optctx + po->u.off - : po->u.dst_ptr; + void *dst = po->flags & (OPT_OFFSET | OPT_SPEC) ? + (uint8_t *)optctx + po->u.off : po->u.dst_ptr; + int *dstcount; if (po->flags & OPT_SPEC) { SpecifierOpt **so = dst; @@ -271,10 +251,9 @@ int parse_option(void *optctx, const char *opt, const char *arg, if (po->flags & OPT_STRING) { char *str; str = av_strdup(arg); + av_freep(dst); *(char **)dst = str; - } else if (po->flags & OPT_BOOL) { - *(int *)dst = bool_val; - } else if (po->flags & OPT_INT) { + } else if (po->flags & OPT_BOOL || po->flags & OPT_INT) { *(int *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); } else if (po->flags & OPT_INT64) { *(int64_t *)dst = parse_number_or_die(opt, arg, OPT_INT64, INT64_MIN, INT64_MAX); @@ -285,8 +264,7 @@ int parse_option(void *optctx, const char *opt, const char *arg, } else if (po->flags & OPT_DOUBLE) { *(double *)dst = parse_number_or_die(opt, arg, OPT_DOUBLE, -INFINITY, INFINITY); } else if (po->u.func_arg) { - int ret = po->flags & OPT_FUNC2 ? po->u.func2_arg(optctx, opt, arg) - : po->u.func_arg(opt, arg); + int ret = po->u.func_arg(optctx, opt, arg); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to set value '%s' for option '%s'\n", arg, opt); @@ -294,7 +272,41 @@ int parse_option(void *optctx, const char *opt, const char *arg, } } if (po->flags & OPT_EXIT) - exit_program(0); + exit(0); + + return 0; +} + +int parse_option(void *optctx, const char *opt, const char *arg, + const OptionDef *options) +{ + const OptionDef *po; + int ret; + + po = find_option(options, opt); + if (!po->name && opt[0] == 'n' && opt[1] == 'o') { + /* handle 'no' bool option */ + po = find_option(options, opt + 2); + if ((po->name && (po->flags & OPT_BOOL))) + arg = "0"; + } else if (po->flags & OPT_BOOL) + arg = "1"; + + if (!po->name) + po = find_option(options, "default"); + if (!po->name) { + av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); + return AVERROR(EINVAL); + } + if (po->flags & HAS_ARG && !arg) { + av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'\n", opt); + return AVERROR(EINVAL); + } + + ret = write_option(optctx, po, opt, arg); + if (ret < 0) + return ret; + return !!(po->flags & HAS_ARG); } @@ -320,7 +332,7 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options opt++; if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0) - exit_program(1); + exit(1); optindex += ret; } else { if (parse_arg_function) @@ -329,6 +341,29 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options } } +int parse_optgroup(void *optctx, OptionGroup *g) +{ + int i, ret; + + av_log(NULL, AV_LOG_DEBUG, "Parsing a group of options: %s %s.\n", + g->group_def->name, g->arg); + + for (i = 0; i < g->nb_opts; i++) { + Option *o = &g->opts[i]; + + av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", + o->key, o->opt->help, o->val); + + ret = write_option(optctx, o->opt, o->key, o->val); + if (ret < 0) + return ret; + } + + av_log(NULL, AV_LOG_DEBUG, "Successfully parsed a group of options.\n"); + + return 0; +} + int locate_option(int argc, char **argv, const OptionDef *options, const char *optname) { @@ -361,16 +396,22 @@ void parse_loglevel(int argc, char **argv, const OptionDef *options) if (!idx) idx = locate_option(argc, argv, options, "v"); if (idx && argv[idx + 1]) - opt_loglevel("loglevel", argv[idx + 1]); + opt_loglevel(NULL, "loglevel", argv[idx + 1]); } #define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0 -int opt_default(const char *opt, const char *arg) +int opt_default(void *optctx, const char *opt, const char *arg) { const AVOption *o; char opt_stripped[128]; const char *p; - const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(), *sc = sws_get_class(); + const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(); +#if CONFIG_AVRESAMPLE + const AVClass *rc = avresample_get_class(); +#endif +#if CONFIG_SWSCALE + const AVClass *sc = sws_get_class(); +#endif if (!(p = strchr(opt, ':'))) p = opt + strlen(opt); @@ -384,6 +425,12 @@ int opt_default(const char *opt, const char *arg) else if ((o = av_opt_find(&fc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) av_dict_set(&format_opts, opt, arg, FLAGS); +#if CONFIG_AVRESAMPLE + else if ((o = av_opt_find(&rc, opt, NULL, 0, + AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) + av_dict_set(&resample_opts, opt, arg, FLAGS); +#endif +#if CONFIG_SWSCALE else if ((o = 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 @@ -393,14 +440,233 @@ int opt_default(const char *opt, const char *arg) return ret; } } +#endif if (o) return 0; - av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); return AVERROR_OPTION_NOT_FOUND; } -int opt_loglevel(const char *opt, const char *arg) +/* + * Check whether given option is a group separator. + * + * @return index of the group definition that matched or -1 if none + */ +static int match_group_separator(const OptionGroupDef *groups, int nb_groups, + const char *opt) +{ + int i; + + for (i = 0; i < nb_groups; i++) { + const OptionGroupDef *p = &groups[i]; + if (p->sep && !strcmp(p->sep, opt)) + return i; + } + + return -1; +} + +/* + * Finish parsing an option group. + * + * @param group_idx which group definition should this group belong to + * @param arg argument of the group delimiting option + */ +static void finish_group(OptionParseContext *octx, int group_idx, + const char *arg) +{ + OptionGroupList *l = &octx->groups[group_idx]; + OptionGroup *g; + + GROW_ARRAY(l->groups, l->nb_groups); + g = &l->groups[l->nb_groups - 1]; + + *g = octx->cur_group; + g->arg = arg; + g->group_def = l->group_def; +#if CONFIG_SWSCALE + g->sws_opts = sws_opts; +#endif + g->codec_opts = codec_opts; + g->format_opts = format_opts; + g->resample_opts = resample_opts; + + codec_opts = NULL; + format_opts = NULL; + resample_opts = NULL; +#if CONFIG_SWSCALE + sws_opts = NULL; +#endif + init_opts(); + + memset(&octx->cur_group, 0, sizeof(octx->cur_group)); +} + +/* + * Add an option instance to currently parsed group. + */ +static void add_opt(OptionParseContext *octx, const OptionDef *opt, + const char *key, const char *val) +{ + int global = !(opt->flags & (OPT_PERFILE | OPT_SPEC | OPT_OFFSET)); + OptionGroup *g = global ? &octx->global_opts : &octx->cur_group; + + GROW_ARRAY(g->opts, g->nb_opts); + g->opts[g->nb_opts - 1].opt = opt; + g->opts[g->nb_opts - 1].key = key; + g->opts[g->nb_opts - 1].val = val; +} + +static void init_parse_context(OptionParseContext *octx, + const OptionGroupDef *groups, int nb_groups) +{ + static const OptionGroupDef global_group = { "global" }; + int i; + + memset(octx, 0, sizeof(*octx)); + + octx->nb_groups = nb_groups; + octx->groups = av_mallocz(sizeof(*octx->groups) * octx->nb_groups); + if (!octx->groups) + exit(1); + + for (i = 0; i < octx->nb_groups; i++) + octx->groups[i].group_def = &groups[i]; + + octx->global_opts.group_def = &global_group; + octx->global_opts.arg = ""; + + init_opts(); +} + +void uninit_parse_context(OptionParseContext *octx) +{ + int i, j; + + for (i = 0; i < octx->nb_groups; i++) { + OptionGroupList *l = &octx->groups[i]; + + for (j = 0; j < l->nb_groups; j++) { + av_freep(&l->groups[j].opts); + 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_freep(&l->groups); + } + av_freep(&octx->groups); + + av_freep(&octx->cur_group.opts); + av_freep(&octx->global_opts.opts); + + uninit_opts(); +} + +int split_commandline(OptionParseContext *octx, int argc, char *argv[], + const OptionDef *options, + const OptionGroupDef *groups, int nb_groups) +{ + int optindex = 1; + + /* perform system-dependent conversions for arguments list */ + prepare_app_arguments(&argc, &argv); + + init_parse_context(octx, groups, nb_groups); + av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n"); + + while (optindex < argc) { + const char *opt = argv[optindex++], *arg; + const OptionDef *po; + int ret; + + av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...", opt); + + /* unnamed group separators, e.g. output filename */ + if (opt[0] != '-' || !opt[1]) { + finish_group(octx, 0, opt); + av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name); + continue; + } + opt++; + +#define GET_ARG(arg) \ +do { \ + arg = argv[optindex++]; \ + if (!arg) { \ + av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\ + return AVERROR(EINVAL); \ + } \ +} while (0) + + /* named group separators, e.g. -i */ + if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) { + GET_ARG(arg); + finish_group(octx, ret, arg); + av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n", + groups[ret].name, arg); + continue; + } + + /* normal options */ + po = find_option(options, opt); + if (po->name) { + if (po->flags & OPT_EXIT) { + /* optional argument, e.g. -h */ + arg = argv[optindex++]; + } else if (po->flags & HAS_ARG) { + GET_ARG(arg); + } else { + arg = "1"; + } + + add_opt(octx, po, opt, arg); + av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " + "argument '%s'.\n", po->name, po->help, arg); + continue; + } + + /* AVOptions */ + if (argv[optindex]) { + ret = opt_default(NULL, opt, argv[optindex]); + if (ret >= 0) { + av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with " + "argument '%s'.\n", opt, argv[optindex]); + optindex++; + continue; + } else if (ret != AVERROR_OPTION_NOT_FOUND) { + av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' " + "with argument '%s'.\n", opt, argv[optindex]); + return ret; + } + } + + /* boolean -nofoo options */ + if (opt[0] == 'n' && opt[1] == 'o' && + (po = find_option(options, opt + 2)) && + po->name && po->flags & OPT_BOOL) { + add_opt(octx, po, opt, "0"); + av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with " + "argument 0.\n", po->name, po->help); + continue; + } + + av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt); + return AVERROR_OPTION_NOT_FOUND; + } + + if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts) + av_log(NULL, AV_LOG_WARNING, "Trailing options were found on the " + "commandline.\n"); + + av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); + + return 0; +} + +int opt_loglevel(void *optctx, const char *opt, const char *arg) { const struct { const char *name; int level; } log_levels[] = { { "quiet" , AV_LOG_QUIET }, @@ -429,13 +695,13 @@ int opt_loglevel(const char *opt, const char *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_program(1); + exit(1); } av_log_set_level(level); return 0; } -int opt_timelimit(const char *opt, const char *arg) +int opt_timelimit(void *optctx, const char *opt, const char *arg) { #if HAVE_SETRLIMIT int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); @@ -515,7 +781,7 @@ void show_banner(void) print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_VERBOSE); } -int show_version(const char *opt, const char *arg) +int show_version(void *optctx, const char *opt, const char *arg) { av_log_set_callback(log_callback_help); printf("%s " LIBAV_VERSION "\n", program_name); @@ -524,7 +790,7 @@ int show_version(const char *opt, const char *arg) return 0; } -int show_license(const char *opt, const char *arg) +int show_license(void *optctx, const char *opt, const char *arg) { printf( #if CONFIG_NONFREE @@ -595,7 +861,7 @@ int show_license(const char *opt, const char *arg) return 0; } -int show_formats(const char *opt, const char *arg) +int show_formats(void *optctx, const char *opt, const char *arg) { AVInputFormat *ifmt = NULL; AVOutputFormat *ofmt = NULL; @@ -686,8 +952,8 @@ static void print_codec(const AVCodec *c) } printf("\n"); } - PRINT_CODEC_SUPPORTED(c, pix_fmts, enum PixelFormat, "pixel formats", - PIX_FMT_NONE, GET_PIX_FMT_NAME); + PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats", + AV_PIX_FMT_NONE, GET_PIX_FMT_NAME); PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0, GET_SAMPLE_RATE_NAME); PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats", @@ -735,18 +1001,20 @@ static void print_codecs_for_id(enum AVCodecID id, int encoder) printf(")"); } -int show_codecs(const char *opt, const char *arg) +int show_codecs(void *optctx, const char *opt, const char *arg) { const AVCodecDescriptor *desc = NULL; printf("Codecs:\n" - " D... = Decoding supported\n" - " .E.. = Encoding supported\n" - " ..V. = Video codec\n" - " ..A. = Audio codec\n" - " ..S. = Subtitle codec\n" - " ...I = Intra frame-only codec\n" - " -----\n"); + " D..... = Decoding supported\n" + " .E.... = Encoding supported\n" + " ..V... = Video codec\n" + " ..A... = Audio codec\n" + " ..S... = Subtitle codec\n" + " ...I.. = Intra frame-only codec\n" + " ....L. = Lossy compression\n" + " .....S = Lossless compression\n" + " -------\n"); while ((desc = avcodec_descriptor_next(desc))) { const AVCodec *codec = NULL; @@ -755,6 +1023,8 @@ int show_codecs(const char *opt, const char *arg) printf("%c", get_media_type_char(desc->type)); printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); + printf((desc->props & AV_CODEC_PROP_LOSSY) ? "L" : "."); + printf((desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : "."); printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); @@ -810,19 +1080,19 @@ static void print_codecs(int encoder) } } -int show_decoders(const char *opt, const char *arg) +int show_decoders(void *optctx, const char *opt, const char *arg) { print_codecs(0); return 0; } -int show_encoders(const char *opt, const char *arg) +int show_encoders(void *optctx, const char *opt, const char *arg) { print_codecs(1); return 0; } -int show_bsfs(const char *opt, const char *arg) +int show_bsfs(void *optctx, const char *opt, const char *arg) { AVBitStreamFilter *bsf = NULL; @@ -833,7 +1103,7 @@ int show_bsfs(const char *opt, const char *arg) return 0; } -int show_protocols(const char *opt, const char *arg) +int show_protocols(void *optctx, const char *opt, const char *arg) { void *opaque = NULL; const char *name; @@ -848,7 +1118,7 @@ int show_protocols(const char *opt, const char *arg) return 0; } -int show_filters(const char *opt, const char *arg) +int show_filters(void *optctx, const char *opt, const char *arg) { AVFilter av_unused(**filter) = NULL; @@ -860,9 +1130,9 @@ int show_filters(const char *opt, const char *arg) return 0; } -int show_pix_fmts(const char *opt, const char *arg) +int show_pix_fmts(void *optctx, const char *opt, const char *arg) { - enum PixelFormat pix_fmt; + const AVPixFmtDescriptor *pix_desc = NULL; printf("Pixel formats:\n" "I.... = Supported Input format for conversion\n" @@ -878,8 +1148,8 @@ int show_pix_fmts(const char *opt, const char *arg) # define sws_isSupportedOutput(x) 0 #endif - for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++) { - const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt]; + while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { + enum AVPixelFormat 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' : '.', @@ -893,7 +1163,7 @@ int show_pix_fmts(const char *opt, const char *arg) return 0; } -int show_sample_fmts(const char *opt, const char *arg) +int show_sample_fmts(void *optctx, const char *opt, const char *arg) { int i; char fmt_str[128]; @@ -988,7 +1258,7 @@ static void show_help_muxer(const char *name) show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM); } -int show_help(const char *opt, const char *arg) +int show_help(void *optctx, const char *opt, const char *arg) { char *topic, *par; av_log_set_callback(log_callback_help); @@ -1019,7 +1289,7 @@ int show_help(const char *opt, const char *arg) int read_yesno(void) { int c = getchar(); - int yesno = (toupper(c) == 'Y'); + int yesno = (av_toupper(c) == 'Y'); while (c != '\n' && c != EOF) c = getchar(); @@ -1057,7 +1327,7 @@ int cmdutils_read_file(const char *filename, char **bufptr, size_t *size) ret = AVERROR_EOF; } else { ret = 0; - (*bufptr)[*size++] = '\0'; + (*bufptr)[(*size)++] = '\0'; } fclose(f); @@ -1192,10 +1462,8 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, if (!codec) codec = s->oformat ? avcodec_find_encoder(codec_id) : avcodec_find_decoder(codec_id); - if (!codec) - return NULL; - switch (codec->type) { + switch (st->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: prefix = 'v'; flags |= AV_OPT_FLAG_VIDEO_PARAM; @@ -1261,13 +1529,13 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) { if (new_size >= INT_MAX / elem_size) { av_log(NULL, AV_LOG_ERROR, "Array too big.\n"); - exit_program(1); + exit(1); } if (*size < new_size) { uint8_t *tmp = av_realloc(array, new_size*elem_size); if (!tmp) { av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); - exit_program(1); + exit(1); } memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); *size = new_size; @@ -1278,13 +1546,19 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbuf) { - FrameBuffer *buf = av_mallocz(sizeof(*buf)); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->pix_fmt); + FrameBuffer *buf; int i, ret; - const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1; + int pixel_size; int h_chroma_shift, v_chroma_shift; int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1 int w = s->width, h = s->height; + if (!desc) + return AVERROR(EINVAL); + pixel_size = desc->comp[0].step_minus1 + 1; + + buf = av_mallocz(sizeof(*buf)); if (!buf) return AVERROR(ENOMEM); @@ -1299,20 +1573,16 @@ static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbu av_freep(&buf); return ret; } - /* XXX this shouldn't be needed, but some tests break without this line - * those decoders are buggy and need to be fixed. - * the following tests fail: - * cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit - */ - memset(buf->base[0], 128, ret); - - avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); + + av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, + &h_chroma_shift, &v_chroma_shift); + for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) { const int h_shift = i==0 ? 0 : h_chroma_shift; const int v_shift = i==0 ? 0 : v_chroma_shift; if (s->flags & CODEC_FLAG_EMU_EDGE) buf->data[i] = buf->base[i]; - else + else if (buf->base[i]) buf->data[i] = buf->base[i] + FFALIGN((buf->linesize[i]*edge >> v_shift) + (pixel_size*edge >> h_shift), 32); @@ -1349,11 +1619,6 @@ int codec_get_buffer(AVCodecContext *s, AVFrame *frame) frame->opaque = buf; frame->type = FF_BUFFER_TYPE_USER; frame->extended_data = frame->data; - frame->pkt_pts = s->pkt ? s->pkt->pts : AV_NOPTS_VALUE; - frame->width = buf->w; - frame->height = buf->h; - frame->format = buf->pix_fmt; - frame->sample_aspect_ratio = s->sample_aspect_ratio; for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) { frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't