X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmdutils.c;h=edeab93ed3cf0318fb4f0586eb6da30ff480818a;hb=571572fcddc16ebe3d60054ae5a2db05800c1d6d;hp=95fa901942b0eda799c3e5c5916a385a0bca78d7;hpb=5afdb3e6b1a06a897ec6d4fe5da1619ae8bef6be;p=ffmpeg diff --git a/cmdutils.c b/cmdutils.c index 95fa901942b..edeab93ed3c 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -41,6 +41,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/mathematics.h" +#include "libavutil/imgutils.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/eval.h" @@ -189,6 +190,7 @@ static const OptionDef *find_option(const OptionDef *po, const char *name) #if defined(_WIN32) && !defined(__MINGW32CE__) #include +#include /* Will be leaked on exit */ static char** win32_argv_utf8 = NULL; static int win32_argc = 0; @@ -422,10 +424,10 @@ void parse_loglevel(int argc, char **argv, const OptionDef *options) } } -#define FLAGS(o) ((o)->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0 +#define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0 int opt_default(const char *opt, const char *arg) { - const AVOption *oc, *of, *os, *oswr = NULL; + const AVOption *o; char opt_stripped[128]; const char *p; const AVClass *cc = avcodec_get_class(), *fc = avformat_get_class(), *sc, *swr_class; @@ -434,18 +436,18 @@ int opt_default(const char *opt, const char *arg) p = opt + strlen(opt); av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1)); - if ((oc = av_opt_find(&cc, opt_stripped, NULL, 0, + if ((o = av_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') && - (oc = av_opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) - av_dict_set(&codec_opts, opt, arg, FLAGS(oc)); - if ((of = av_opt_find(&fc, opt, NULL, 0, - AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) - av_dict_set(&format_opts, opt, arg, FLAGS(of)); + (o = av_opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) + av_dict_set(&codec_opts, opt, arg, FLAGS); + 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_SWSCALE sc = sws_get_class(); - if ((os = av_opt_find(&sc, opt, NULL, 0, - AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { + if (!o && (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 int ret = av_opt_set(sws_opts, opt, arg, 0); if (ret < 0) { @@ -456,8 +458,8 @@ int opt_default(const char *opt, const char *arg) #endif #if CONFIG_SWRESAMPLE swr_class = swr_get_class(); - if (!oc && !of && !os && (oswr = av_opt_find(&swr_class, opt, NULL, 0, - AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { + if (!o && (o = av_opt_find(&swr_class, opt, NULL, 0, + AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { int ret = av_opt_set(swr_opts, opt, arg, 0); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt); @@ -466,7 +468,7 @@ int opt_default(const char *opt, const char *arg) } #endif - if (oc || of || os || oswr) + if (o) return 0; av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); return AVERROR_OPTION_NOT_FOUND; @@ -653,8 +655,9 @@ static void print_program_info(int flags, int level) av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers", program_birth_year, this_year); av_log(NULL, level, "\n"); - av_log(NULL, level, "%sbuilt on %s %s with %s %s\n", - indent, __DATE__, __TIME__, CC_TYPE, CC_VERSION); + av_log(NULL, level, "%sbuilt on %s %s with %s\n", + indent, __DATE__, __TIME__, CC_IDENT); + av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent); } @@ -811,15 +814,21 @@ int opt_codecs(const char *opt, const char *arg) AVCodec *p = NULL, *p2; const char *last_name; printf("Codecs:\n" - " D..... = Decoding supported\n" - " .E.... = Encoding supported\n" - " ..V... = Video codec\n" - " ..A... = Audio codec\n" - " ..S... = Subtitle codec\n" - " ...S.. = Supports draw_horiz_band\n" - " ....D. = Supports direct rendering method 1\n" - " .....T = Supports weird frame truncation\n" - " ------\n"); + " D....... = Decoding supported\n" + " .E...... = Encoding supported\n" + " ..V..... = Video codec\n" + " ..A..... = Audio codec\n" + " ..S..... = Subtitle codec\n" + " ...S.... = Supports draw_horiz_band\n" + " ....D... = Supports direct rendering method 1\n" + " .....T.. = Supports weird frame truncation\n" + " ......F. = Supports frame-based multi-threaded decoding\n" + " ......S. = Supports slice-based multi-threaded decoding\n" + " ......B. = Supports both frame-based and slice-based multi-threaded decoding\n" + " .......F = Supports frame-based multi-threaded encoding\n" + " .......S = Supports slice-based multi-threaded encoding\n" + " .......B = Supports both frame-based and slice-based multi-threaded encoding\n" + " --------\n"); last_name= "000"; for (;;) { int decode = 0; @@ -845,13 +854,21 @@ int opt_codecs(const char *opt, const char *arg) break; last_name = p2->name; - printf(" %s%s%c%s%s%s %-15s %s", + printf(" %s%s%c%s%s%s%s%s %-15s %s", decode ? "D" : (/* p2->decoder ? "d" : */ " "), encode ? "E" : " ", get_media_type_char(p2->type), cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S" : " ", cap & CODEC_CAP_DR1 ? "D" : " ", cap & CODEC_CAP_TRUNCATED ? "T" : " ", + decode ? + cap & CODEC_CAP_FRAME_THREADS ? cap & CODEC_CAP_SLICE_THREADS ? "B" : "F" : + cap & CODEC_CAP_SLICE_THREADS ? "S" : " " + : " ", + encode ? + cap & CODEC_CAP_FRAME_THREADS ? cap & CODEC_CAP_SLICE_THREADS ? "B" : "F" : + cap & CODEC_CAP_SLICE_THREADS ? "S" : " " + : " ", p2->name, p2->long_name ? p2->long_name : ""); #if 0 @@ -1071,66 +1088,14 @@ FILE *get_preset_file(char *filename, size_t filename_size, int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) { - if (*spec <= '9' && *spec >= '0') /* opt:index */ - return strtol(spec, NULL, 0) == st->index; - else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || - *spec == 't') { /* opt:[vasdt] */ - enum AVMediaType type; - - switch (*spec++) { - case 'v': type = AVMEDIA_TYPE_VIDEO; break; - case 'a': type = AVMEDIA_TYPE_AUDIO; break; - case 's': type = AVMEDIA_TYPE_SUBTITLE; break; - case 'd': type = AVMEDIA_TYPE_DATA; break; - case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; - default: av_assert0(0); - } - if (type != st->codec->codec_type) - return 0; - if (*spec++ == ':') { /* possibly followed by :index */ - int i, index = strtol(spec, NULL, 0); - for (i = 0; i < s->nb_streams; i++) - if (s->streams[i]->codec->codec_type == type && index-- == 0) - return i == st->index; - return 0; - } - return 1; - } else if (*spec == 'p' && *(spec + 1) == ':') { - int prog_id, i, j; - char *endptr; - spec += 2; - prog_id = strtol(spec, &endptr, 0); - for (i = 0; i < s->nb_programs; i++) { - if (s->programs[i]->id != prog_id) - continue; - - if (*endptr++ == ':') { - int stream_idx = strtol(endptr, NULL, 0); - return stream_idx >= 0 && - stream_idx < s->programs[i]->nb_stream_indexes && - st->index == s->programs[i]->stream_index[stream_idx]; - } - - for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) - if (st->index == s->programs[i]->stream_index[j]) - return 1; - } - return 0; - } else if (*spec == '#') { - int sid; - char *endptr; - sid = strtol(spec + 1, &endptr, 0); - if (!*endptr) - return st->id == sid; - } else if (!*spec) /* empty specifier, matches everything */ - return 1; - - av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); - return AVERROR(EINVAL); + int ret = avformat_match_stream_specifier(s, st, spec); + if (ret < 0) + av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); + return ret; } -AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec, - AVFormatContext *s, AVStream *st) +AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id, + AVFormatContext *s, AVStream *st, AVCodec *codec) { AVDictionary *ret = NULL; AVDictionaryEntry *t = NULL; @@ -1139,6 +1104,9 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec, char prefix = 0; const AVClass *cc = avcodec_get_class(); + if (!codec) + codec = s->oformat ? avcodec_find_encoder(codec_id) + : avcodec_find_decoder(codec_id); if (!codec) return NULL; @@ -1199,8 +1167,8 @@ 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, avcodec_find_decoder(s->streams[i]->codec->codec_id), - s, s->streams[i]); + opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id, + s, s->streams[i], NULL); return opts; } @@ -1222,3 +1190,149 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) } return array; } + +static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbuf) +{ + FrameBuffer *buf = av_mallocz(sizeof(*buf)); + int i, ret; + const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1; + 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 (!buf) + return AVERROR(ENOMEM); + + avcodec_align_dimensions(s, &w, &h); + + if (!(s->flags & CODEC_FLAG_EMU_EDGE)) { + w += 2*edge; + h += 2*edge; + } + + if ((ret = av_image_alloc(buf->base, buf->linesize, w, h, + s->pix_fmt, 32)) < 0) { + av_freep(&buf); + av_log(s, AV_LOG_ERROR, "alloc_buffer: av_image_alloc() failed\n"); + 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); + 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->linesize[i] || !buf->base[i]) + buf->data[i] = buf->base[i]; + else + buf->data[i] = buf->base[i] + + FFALIGN((buf->linesize[i]*edge >> v_shift) + + (pixel_size*edge >> h_shift), 32); + } + buf->w = s->width; + buf->h = s->height; + buf->pix_fmt = s->pix_fmt; + buf->pool = pool; + + *pbuf = buf; + return 0; +} + +int codec_get_buffer(AVCodecContext *s, AVFrame *frame) +{ + FrameBuffer **pool = s->opaque; + FrameBuffer *buf; + int ret, i; + + if(av_image_check_size(s->width, s->height, 0, s) || s->pix_fmt<0) { + av_log(s, AV_LOG_ERROR, "codec_get_buffer: image parameters invalid\n"); + return -1; + } + + if (!*pool && (ret = alloc_buffer(pool, s, pool)) < 0) + return ret; + + buf = *pool; + *pool = buf->next; + buf->next = NULL; + if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) { + av_freep(&buf->base[0]); + av_free(buf); + if ((ret = alloc_buffer(pool, s, &buf)) < 0) + return ret; + } + av_assert0(!buf->refcount); + buf->refcount++; + + 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 + frame->data[i] = buf->data[i]; + frame->linesize[i] = buf->linesize[i]; + } + + return 0; +} + +static void unref_buffer(FrameBuffer *buf) +{ + FrameBuffer **pool = buf->pool; + + av_assert0(buf->refcount > 0); + buf->refcount--; + if (!buf->refcount) { + FrameBuffer *tmp; + for(tmp= *pool; tmp; tmp= tmp->next) + av_assert1(tmp != buf); + + buf->next = *pool; + *pool = buf; + } +} + +void codec_release_buffer(AVCodecContext *s, AVFrame *frame) +{ + FrameBuffer *buf = frame->opaque; + int i; + + if(frame->type!=FF_BUFFER_TYPE_USER) { + avcodec_default_release_buffer(s, frame); + return; + } + + for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++) + frame->data[i] = NULL; + + unref_buffer(buf); +} + +void filter_release_buffer(AVFilterBuffer *fb) +{ + FrameBuffer *buf = fb->priv; + av_free(fb); + unref_buffer(buf); +} + +void free_buffer_pool(FrameBuffer **pool) +{ + FrameBuffer *buf = *pool; + while (buf) { + *pool = buf->next; + av_freep(&buf->base[0]); + av_free(buf); + buf = *pool; + } +}