Skip to content
Snippets Groups Projects
cmdutils.c 70.1 KiB
Newer Older
  • Learn to ignore specific revisions
  •         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:         exit_program(1);
    
            if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
    
                 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_array(s->nb_streams, sizeof(*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);
    
            uint8_t *tmp = av_realloc_array(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;
    }
    
    
    #if CONFIG_AVDEVICE
    static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts)
    {
        int ret, i;
        AVFormatContext *dev = NULL;
        AVDeviceInfoList *device_list = NULL;
        AVDictionary *tmp_opts = NULL;
    
        if (!fmt || !fmt->priv_class  || !AV_IS_INPUT_DEVICE(fmt->priv_class->category))
            return AVERROR(EINVAL);
    
        printf("Audo-detected sources for %s:\n", fmt->name);
        if (!fmt->get_device_list) {
            ret = AVERROR(ENOSYS);
            printf("Cannot list sources. Not implemented.\n");
            goto fail;
        }
    
        /* TODO: avformat_open_input calls read_header callback which is not necessary.
                 Function like avformat_alloc_output_context2 for input could be helpful here. */
        av_dict_copy(&tmp_opts, opts, 0);
        if ((ret = avformat_open_input(&dev, NULL, fmt, &tmp_opts)) < 0) {
            printf("Cannot open device: %s.\n", fmt->name);
            goto fail;
        }
    
        if ((ret = avdevice_list_devices(dev, &device_list)) < 0) {
            printf("Cannot list sources.\n");
            goto fail;
        }
    
        for (i = 0; i < device_list->nb_devices; i++) {
            printf("%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
                   device_list->devices[i]->device_name, device_list->devices[i]->device_description);
        }
    
      fail:
        av_dict_free(&tmp_opts);
        avdevice_free_list_devices(&device_list);
        avformat_close_input(&dev);
        return ret;
    }
    
    static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts)
    {
        int ret, i;
        AVFormatContext *dev = NULL;
        AVDeviceInfoList *device_list = NULL;
        AVDictionary *tmp_opts = NULL;
    
        if (!fmt || !fmt->priv_class  || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category))
            return AVERROR(EINVAL);
    
        printf("Audo-detected sinks for %s:\n", fmt->name);
        if (!fmt->get_device_list) {
            ret = AVERROR(ENOSYS);
            printf("Cannot list sinks. Not implemented.\n");
            goto fail;
        }
    
        if ((ret = avformat_alloc_output_context2(&dev, fmt, NULL, NULL)) < 0) {
            printf("Cannot open device: %s.\n", fmt->name);
            goto fail;
        }
        av_dict_copy(&tmp_opts, opts, 0);
        av_opt_set_dict2(dev, &tmp_opts, AV_OPT_SEARCH_CHILDREN);
    
        if ((ret = avdevice_list_devices(dev, &device_list)) < 0) {
            printf("Cannot list sinks.\n");
            goto fail;
        }
    
        for (i = 0; i < device_list->nb_devices; i++) {
            printf("%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
                   device_list->devices[i]->device_name, device_list->devices[i]->device_description);
        }
    
      fail:
        av_dict_free(&tmp_opts);
        avdevice_free_list_devices(&device_list);
        avformat_free_context(dev);
        return ret;
    }
    
    static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionary **opts)
    {
        int ret;
        if (arg) {
            char *opts_str = NULL;
            av_assert0(dev && opts);
            *dev = av_strdup(arg);
            if (!*dev)
                return AVERROR(ENOMEM);
            if ((opts_str = strchr(*dev, ','))) {
                *(opts_str++) = '\0';
                if (opts_str[0] && ((ret = av_dict_parse_string(opts, opts_str, "=", ":", 0)) < 0)) {
                    av_freep(dev);
                    return ret;
                }
            }
        } else
            printf("\nDevice name is not provided.\n"
                    "You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.\n\n");
        return 0;
    }
    
    int show_sources(void *optctx, const char *opt, const char *arg)
    {
        AVInputFormat *fmt = NULL;
        char *dev = NULL;
        AVDictionary *opts = NULL;
        int ret = 0;
        int error_level = av_log_get_level();
    
        av_log_set_level(AV_LOG_ERROR);
    
        if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
            goto fail;
    
        do {
            fmt = av_input_audio_device_next(fmt);
            if (fmt) {
                if (!strcmp(fmt->name, "lavfi"))
                    continue; //it's pointless to probe lavfi
                if (dev && strcmp(fmt->name, dev))
                    continue;
                print_device_sources(fmt, opts);
            }
        } while (fmt);
        do {
            fmt = av_input_video_device_next(fmt);
            if (fmt) {
                if (dev && strcmp(fmt->name, dev))
                    continue;
                print_device_sources(fmt, opts);
            }
        } while (fmt);
      fail:
        av_dict_free(&opts);
        av_free(dev);
        av_log_set_level(error_level);
        return ret;
    }
    
    int show_sinks(void *optctx, const char *opt, const char *arg)
    {
        AVOutputFormat *fmt = NULL;
        char *dev = NULL;
        AVDictionary *opts = NULL;
        int ret = 0;
        int error_level = av_log_get_level();
    
        av_log_set_level(AV_LOG_ERROR);
    
        if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
            goto fail;
    
        do {
            fmt = av_output_audio_device_next(fmt);
            if (fmt) {
                if (dev && strcmp(fmt->name, dev))
                    continue;
                print_device_sinks(fmt, opts);
            }
        } while (fmt);
        do {
            fmt = av_output_video_device_next(fmt);
            if (fmt) {
                if (dev && strcmp(fmt->name, dev))
                    continue;
                print_device_sinks(fmt, opts);
            }
        } while (fmt);
      fail:
        av_dict_free(&opts);
        av_free(dev);
        av_log_set_level(error_level);
        return ret;
    }
    #endif