X-Git-Url: https://git.piment-noir.org/?p=deb_ffmpeg.git;a=blobdiff_plain;f=ffmpeg%2Fcmdutils.c;h=b68dae97539d3c4acd29b3fda8bd9f978d28f21c;hp=1143ea10d1467df845ec3766b664adf165e4cd0f;hb=f6fa7814ccfe3e76514b36cf04f5cd3cb657c8cf;hpb=2ba45a602cbfa7b771effba9b11bb4245c21bc00 diff --git a/ffmpeg/cmdutils.c b/ffmpeg/cmdutils.c index 1143ea1..b68dae9 100644 --- a/ffmpeg/cmdutils.c +++ b/ffmpeg/cmdutils.c @@ -444,7 +444,7 @@ int locate_option(int argc, char **argv, const OptionDef *options, (po->name && !strcmp(optname, po->name))) return i; - if (po->flags & HAS_ARG) + if (!po->name || po->flags & HAS_ARG) i++; } return 0; @@ -959,9 +959,10 @@ static int init_report(const char *env) report_file = fopen(filename.str, "w"); if (!report_file) { + int ret = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n", filename.str, strerror(errno)); - return AVERROR(errno); + return ret; } av_log_set_callback(log_callback_report); av_log(NULL, AV_LOG_INFO, @@ -1543,7 +1544,8 @@ int show_protocols(void *optctx, const char *opt, const char *arg) int show_filters(void *optctx, const char *opt, const char *arg) { - const AVFilter av_unused(*filter) = NULL; +#if CONFIG_AVFILTER + const AVFilter *filter = NULL; char descr[64], *descr_cur; int i, j; const AVFilterPad *pad; @@ -1556,7 +1558,6 @@ int show_filters(void *optctx, const char *opt, const char *arg) " V = Video input/output\n" " N = Dynamic number and/or type of input/output\n" " | = Source or sink filter\n"); -#if CONFIG_AVFILTER while ((filter = avfilter_next(filter))) { descr_cur = descr; for (i = 0; i < 2; i++) { @@ -1581,6 +1582,8 @@ int show_filters(void *optctx, const char *opt, const char *arg) filter->process_command ? 'C' : '.', filter->name, descr, filter->description); } +#else + printf("No filters available: libavfilter disabled\n"); #endif return 0; } @@ -1861,17 +1864,19 @@ int cmdutils_read_file(const char *filename, char **bufptr, size_t *size) FILE *f = av_fopen_utf8(filename, "rb"); if (!f) { + ret = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, strerror(errno)); - return AVERROR(errno); + return ret; } fseek(f, 0, SEEK_END); *size = ftell(f); fseek(f, 0, SEEK_SET); if (*size == (size_t)-1) { + ret = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "IO error: %s\n", strerror(errno)); fclose(f); - return AVERROR(errno); + return ret; } *bufptr = av_malloc(*size + 1); if (!*bufptr) { @@ -1883,9 +1888,9 @@ int cmdutils_read_file(const char *filename, char **bufptr, size_t *size) if (ret < *size) { av_free(*bufptr); if (ferror(f)) { + ret = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "Error while reading file '%s': %s\n", filename, strerror(errno)); - ret = AVERROR(errno); } else ret = AVERROR_EOF; } else { @@ -1992,7 +1997,7 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, switch (check_stream_specifier(s, st, p + 1)) { case 1: *p = 0; break; case 0: continue; - default: return NULL; + default: exit_program(1); } if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || @@ -2050,3 +2055,184 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) } 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