Skip to content
Snippets Groups Projects
cmdutils.c 49 KiB
Newer Older
  • Learn to ignore specific revisions
  •     while ((bsf = av_bitstream_filter_next(bsf)))
    
        printf("\n");
    
    int show_protocols(const char *opt, const char *arg)
    
        void *opaque = NULL;
        const char *name;
    
        printf("Supported file protocols:\n"
    
               "Input:\n");
        while ((name = avio_enum_protocols(&opaque, 0)))
            printf("%s\n", name);
        printf("Output:\n");
        while ((name = avio_enum_protocols(&opaque, 1)))
            printf("%s\n", name);
    
    int show_filters(const char *opt, const char *arg)
    
        AVFilter av_unused(**filter) = NULL;
    
        char descr[64], *descr_cur;
        int i, j;
        const AVFilterPad *pad;
    
        while ((filter = av_filter_next(filter)) && *filter) {
            descr_cur = descr;
            for (i = 0; i < 2; i++) {
                if (i) {
                    *(descr_cur++) = '-';
                    *(descr_cur++) = '>';
                }
                pad = i ? (*filter)->outputs : (*filter)->inputs;
                for (j = 0; pad[j].name; j++) {
                    if (descr_cur >= descr + sizeof(descr) - 4)
                        break;
                    *(descr_cur++) = get_media_type_char(pad[j].type);
                }
                if (!j)
                    *(descr_cur++) = '|';
            }
            *descr_cur = 0;
            printf("%-16s %-10s %s\n", (*filter)->name, descr, (*filter)->description);
        }
    
    int show_pix_fmts(const char *opt, const char *arg)
    
        printf("Pixel formats:\n"
               "I.... = Supported Input  format for conversion\n"
               ".O... = Supported Output format for conversion\n"
               "..H.. = Hardware accelerated format\n"
               "...P. = Paletted format\n"
               "....B = Bitstream format\n"
               "FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL\n"
               "-----\n");
    
    #if !CONFIG_SWSCALE
    #   define sws_isSupportedInput(x)  0
    #   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];
    
            if(!pix_desc->name)
                continue;
    
            printf("%c%c%c%c%c %-16s       %d            %2d\n",
                   sws_isSupportedInput (pix_fmt)      ? 'I' : '.',
                   sws_isSupportedOutput(pix_fmt)      ? 'O' : '.',
                   pix_desc->flags & PIX_FMT_HWACCEL   ? 'H' : '.',
                   pix_desc->flags & PIX_FMT_PAL       ? 'P' : '.',
                   pix_desc->flags & PIX_FMT_BITSTREAM ? 'B' : '.',
                   pix_desc->name,
                   pix_desc->nb_components,
                   av_get_bits_per_pixel(pix_desc));
        }
    
    int show_sample_fmts(const char *opt, const char *arg)
    {
        int i;
        char fmt_str[128];
        for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
            printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
        return 0;
    }
    
    
    static void show_help_codec(const char *name, int encoder)
    {
        const AVCodecDescriptor *desc;
        const AVCodec *codec;
    
        if (!name) {
            av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n");
            return;
        }
    
        codec = encoder ? avcodec_find_encoder_by_name(name) :
                          avcodec_find_decoder_by_name(name);
    
        if (codec)
            print_codec(codec);
        else if ((desc = avcodec_descriptor_get_by_name(name))) {
            int printed = 0;
    
            while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
                printed = 1;
                print_codec(codec);
            }
    
            if (!printed) {
    
                av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to FFmpeg, "
                       "but no %s for it are available. FFmpeg might need to be "
    
                       "recompiled with additional external libraries.\n",
                       name, encoder ? "encoders" : "decoders");
            }
        } else {
    
            av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n",
    
    static void show_help_demuxer(const char *name)
    {
        const AVInputFormat *fmt = av_find_input_format(name);
    
        if (!fmt) {
            av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
            return;
        }
    
        printf("Demuxer %s [%s]:\n", fmt->name, fmt->long_name);
    
        if (fmt->extensions)
            printf("    Common extensions: %s.\n", fmt->extensions);
    
        if (fmt->priv_class)
            show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM);
    }
    
    static void show_help_muxer(const char *name)
    {
        const AVCodecDescriptor *desc;
        const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL);
    
        if (!fmt) {
            av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name);
            return;
        }
    
        printf("Muxer %s [%s]:\n", fmt->name, fmt->long_name);
    
        if (fmt->extensions)
            printf("    Common extensions: %s.\n", fmt->extensions);
        if (fmt->mime_type)
            printf("    Mime type: %s.\n", fmt->mime_type);
        if (fmt->video_codec != AV_CODEC_ID_NONE &&
            (desc = avcodec_descriptor_get(fmt->video_codec))) {
            printf("    Default video codec: %s.\n", desc->name);
        }
        if (fmt->audio_codec != AV_CODEC_ID_NONE &&
            (desc = avcodec_descriptor_get(fmt->audio_codec))) {
            printf("    Default audio codec: %s.\n", desc->name);
        }
        if (fmt->subtitle_codec != AV_CODEC_ID_NONE &&
            (desc = avcodec_descriptor_get(fmt->subtitle_codec))) {
            printf("    Default subtitle codec: %s.\n", desc->name);
        }
    
        if (fmt->priv_class)
            show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM);
    }
    
    
    int show_help(const char *opt, const char *arg)
    {
        char *topic, *par;
        av_log_set_callback(log_callback_help);
    
        topic = av_strdup(arg ? arg : "");
        par = strchr(topic, '=');
        if (par)
            *par++ = 0;
    
        if (!*topic) {
            show_help_default(topic, par);
        } else if (!strcmp(topic, "decoder")) {
            show_help_codec(par, 0);
        } else if (!strcmp(topic, "encoder")) {
            show_help_codec(par, 1);
    
        } else if (!strcmp(topic, "demuxer")) {
            show_help_demuxer(par);
        } else if (!strcmp(topic, "muxer")) {
            show_help_muxer(par);
    
        } else {
            show_help_default(topic, par);
        }
    
        av_freep(&topic);
        return 0;
    }
    
    
    int read_yesno(void)
    {
        int c = getchar();
        int yesno = (toupper(c) == 'Y');
    
        while (c != '\n' && c != EOF)
            c = getchar();
    
        return yesno;
    }
    
    int cmdutils_read_file(const char *filename, char **bufptr, size_t *size)
    
        FILE *f = fopen(filename, "rb");
    
            av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename,
                   strerror(errno));
    
            return AVERROR(errno);
        }
        fseek(f, 0, SEEK_END);
        *size = ftell(f);
        fseek(f, 0, SEEK_SET);
        *bufptr = av_malloc(*size + 1);
        if (!*bufptr) {
    
            av_log(NULL, AV_LOG_ERROR, "Could not allocate file buffer\n");
    
        ret = fread(*bufptr, 1, *size, f);
        if (ret < *size) {
            av_free(*bufptr);
            if (ferror(f)) {
                av_log(NULL, AV_LOG_ERROR, "Error while reading file '%s': %s\n",
                       filename, strerror(errno));
                ret = AVERROR(errno);
            } else
                ret = AVERROR_EOF;
        } else {
            ret = 0;
            (*bufptr)[*size++] = '\0';
        }
    
        return ret;
    
    FILE *get_preset_file(char *filename, size_t filename_size,
    
                          const char *preset_name, int is_path,
                          const char *codec_name)
    
        const char *base[3] = { getenv("FFMPEG_DATADIR"),
    
                                getenv("HOME"),
    
    
        if (is_path) {
            av_strlcpy(filename, preset_name, filename_size);
            f = fopen(filename, "r");
        } else {
    
    Gianluigi Tiesi's avatar
    Gianluigi Tiesi committed
    #ifdef _WIN32
            char datadir[MAX_PATH], *ls;
            base[2] = NULL;
    
            if (GetModuleFileNameA(GetModuleHandleA(NULL), datadir, sizeof(datadir) - 1))
            {
                for (ls = datadir; ls < datadir + strlen(datadir); ls++)
                    if (*ls == '\\') *ls = '/';
    
                if (ls = strrchr(datadir, '/'))
                {
                    *ls = 0;
                    strncat(datadir, "/ffpresets",  sizeof(datadir) - 1 - strlen(datadir));
                    base[2] = datadir;
                }
            }
    #endif
    
            for (i = 0; i < 3 && !f; i++) {
                if (!base[i])
                    continue;
    
                snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i],
    
                         i != 1 ? "" : "/.ffmpeg", preset_name);
    
                f = fopen(filename, "r");
                if (!f && codec_name) {
                    snprintf(filename, filename_size,
    
                             "%s%s/%s-%s.ffpreset",
    
                             base[i], i != 1 ? "" : "/.ffmpeg", codec_name,
    
                             preset_name);
    
    int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
    {
    
        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, enum AVCodecID codec_id,
    
                                    AVFormatContext *s, AVStream *st, AVCodec *codec)
    
    {
        AVDictionary    *ret = NULL;
        AVDictionaryEntry *t = NULL;
    
        int            flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM
                                          : AV_OPT_FLAG_DECODING_PARAM;
    
        const AVClass    *cc = avcodec_get_class();
    
        if (!codec)
            codec            = s->oformat ? avcodec_find_encoder(codec_id)
                                          : avcodec_find_decoder(codec_id);
    
        case AVMEDIA_TYPE_VIDEO:
            prefix  = 'v';
            flags  |= AV_OPT_FLAG_VIDEO_PARAM;
            break;
        case AVMEDIA_TYPE_AUDIO:
            prefix  = 'a';
            flags  |= AV_OPT_FLAG_AUDIO_PARAM;
            break;
        case AVMEDIA_TYPE_SUBTITLE:
            prefix  = 's';
            flags  |= AV_OPT_FLAG_SUBTITLE_PARAM;
            break;
    
        }
    
        while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) {
    
            char *p = strchr(t->key, ':');
    
            /* check stream specification in opt name */
            if (p)
                switch (check_stream_specifier(s, st, p + 1)) {
                case  1: *p = 0; break;
                case  0:         continue;
                default:         return NULL;
                }
    
    
            if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
    
                (codec && codec->priv_class &&
                 av_opt_find(&codec->priv_class, t->key, NULL, flags,
                             AV_OPT_SEARCH_FAKE_OBJ)))
    
                av_dict_set(&ret, t->key, t->value, 0);
    
            else if (t->key[0] == prefix &&
                     av_opt_find(&cc, t->key + 1, NULL, flags,
                                 AV_OPT_SEARCH_FAKE_OBJ))
                av_dict_set(&ret, t->key + 1, t->value, 0);
    
    AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
                                               AVDictionary *codec_opts)
    
    {
        int i;
        AVDictionary **opts;
    
        if (!s->nb_streams)
            return NULL;
        opts = av_mallocz(s->nb_streams * sizeof(*opts));
        if (!opts) {
    
            av_log(NULL, AV_LOG_ERROR,
                   "Could not alloc memory for stream options.\n");
    
            return NULL;
        }
        for (i = 0; i < s->nb_streams; i++)
    
            opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id,
    
    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);
        }
        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);
            }
            memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
            *size = new_size;
            return tmp;
        }
        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");
    
        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);
    
        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;
        }
    }