Merge remote-tracking branch 'qatar/master'
[ffmpeg.git] / cmdutils.c
index 758a9a0..36f82c9 100644 (file)
 #include "libavformat/avformat.h"
 #include "libavfilter/avfilter.h"
 #include "libavdevice/avdevice.h"
+#include "libavresample/avresample.h"
 #include "libswscale/swscale.h"
 #include "libswresample/swresample.h"
 #if CONFIG_POSTPROC
 #include "libpostproc/postprocess.h"
 #endif
+#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"
@@ -63,11 +66,13 @@ static FILE *report_file;
 
 void init_opts(void)
 {
-#if CONFIG_SWSCALE
-    sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC,
+
+    if(CONFIG_SWSCALE)
+        sws_opts = sws_getContext(16, 16, 0, 16, 16, 0, SWS_BICUBIC,
                               NULL, NULL, NULL);
-#endif
-    swr_opts = swr_alloc();
+
+    if(CONFIG_SWRESAMPLE)
+        swr_opts = swr_alloc();
 }
 
 void uninit_opts(void)
@@ -76,7 +81,10 @@ void uninit_opts(void)
     sws_freeContext(sws_opts);
     sws_opts = NULL;
 #endif
-    swr_free(&swr_opts);
+
+    if(CONFIG_SWRESAMPLE)
+        swr_free(&swr_opts);
+
     av_dict_free(&format_opts);
     av_dict_free(&codec_opts);
 }
@@ -415,10 +423,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;
@@ -427,18 +435,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) {
@@ -447,17 +455,19 @@ 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);
             return ret;
         }
     }
+#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;
@@ -546,38 +556,10 @@ int opt_max_alloc(const char *opt, const char *arg)
 
 int opt_cpuflags(const char *opt, const char *arg)
 {
-    static const AVOption cpuflags_opts[] = {
-        { "flags"   , NULL, 0, AV_OPT_TYPE_FLAGS, { 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
-        { "altivec" , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ALTIVEC  },    .unit = "flags" },
-        { "mmx"     , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_MMX      },    .unit = "flags" },
-        { "mmx2"    , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_MMX2     },    .unit = "flags" },
-        { "sse"     , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE      },    .unit = "flags" },
-        { "sse2"    , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE2     },    .unit = "flags" },
-        { "sse2slow", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE2SLOW },    .unit = "flags" },
-        { "sse3"    , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE3     },    .unit = "flags" },
-        { "sse3slow", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE3SLOW },    .unit = "flags" },
-        { "ssse3"   , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSSE3    },    .unit = "flags" },
-        { "atom"    , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ATOM     },    .unit = "flags" },
-        { "sse4.1"  , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE4     },    .unit = "flags" },
-        { "sse4.2"  , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_SSE42    },    .unit = "flags" },
-        { "avx"     , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_AVX      },    .unit = "flags" },
-        { "xop"     , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_XOP      },    .unit = "flags" },
-        { "fma4"    , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_FMA4     },    .unit = "flags" },
-        { "3dnow"   , NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_3DNOW    },    .unit = "flags" },
-        { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_3DNOWEXT },    .unit = "flags" },
-        { NULL },
-    };
-    static const AVClass class = {
-        .class_name = "cpuflags",
-        .item_name  = av_default_item_name,
-        .option     = cpuflags_opts,
-        .version    = LIBAVUTIL_VERSION_INT,
-    };
-    int flags = av_get_cpu_flags();
     int ret;
-    const AVClass *pclass = &class;
+    unsigned flags = av_get_cpu_flags();
 
-    if ((ret = av_opt_eval_flags(&pclass, &cpuflags_opts[0], arg, &flags)) < 0)
+    if ((ret = av_parse_cpu_caps(&flags, arg)) < 0)
         return ret;
 
     av_force_cpu_flags(flags);
@@ -625,7 +607,8 @@ static int warned_cfg = 0;
         const char *indent = flags & INDENT? "  " : "";                 \
         if (flags & SHOW_VERSION) {                                     \
             unsigned int version = libname##_version();                 \
-            av_log(NULL, level, "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",\
+            av_log(NULL, level,                                         \
+                   "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",            \
                    indent, #libname,                                    \
                    LIB##LIBNAME##_VERSION_MAJOR,                        \
                    LIB##LIBNAME##_VERSION_MINOR,                        \
@@ -654,6 +637,7 @@ static void print_all_libs_info(int flags, int 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);
 #if CONFIG_POSTPROC
@@ -828,15 +812,18 @@ 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-threading\n"
+           " ......S = Supports slice-based multi-threading\n"
+           " ......B = Supports both frame-based and slice-based multi-threading\n"
+           " --------\n");
     last_name= "000";
     for (;;) {
         int decode = 0;
@@ -862,13 +849,15 @@ 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 %-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" : " ",
+               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
@@ -1100,7 +1089,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
         case 's': type = AVMEDIA_TYPE_SUBTITLE;   break;
         case 'd': type = AVMEDIA_TYPE_DATA;       break;
         case 't': type = AVMEDIA_TYPE_ATTACHMENT; break;
-        default: abort(); // never reached, silence warning
+        default:  av_assert0(0);
         }
         if (type != st->codec->codec_type)
             return 0;
@@ -1133,6 +1122,12 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
                     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;
 
@@ -1140,8 +1135,8 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
     return AVERROR(EINVAL);
 }
 
-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;
@@ -1151,6 +1146,9 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec,
     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;
 
     switch (codec->type) {
@@ -1210,8 +1208,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;
 }
 
@@ -1233,3 +1231,146 @@ 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);
+        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[1] || !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)
+        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;
+    }
+}