From: Diederick Niehorster <dcnieho@gmail.com> To: ffmpeg-devel@ffmpeg.org Cc: Diederick Niehorster <dcnieho@gmail.com> Subject: [FFmpeg-devel] [PATCH v4 20/22] doc/examples: adding device_get_capabilities example Date: Fri, 25 Mar 2022 15:10:39 +0100 Message-ID: <20220325141041.1748-21-dcnieho@gmail.com> (raw) In-Reply-To: <20220325141041.1748-1-dcnieho@gmail.com> This example also shows use of get_device_list API. Also improve capability API doc in avdevice.h: now point to this example instead of rough example code given in the header. Signed-off-by: Diederick Niehorster <dcnieho@gmail.com> --- configure | 2 + doc/examples/.gitignore | 1 + doc/examples/Makefile | 1 + doc/examples/Makefile.example | 1 + doc/examples/device_get_capabilities.c | 243 +++++++++++++++++++++++++ libavdevice/avdevice.h | 33 +--- 6 files changed, 249 insertions(+), 32 deletions(-) create mode 100644 doc/examples/device_get_capabilities.c diff --git a/configure b/configure index a7953ffc16..5c361f91a0 100755 --- a/configure +++ b/configure @@ -1726,6 +1726,7 @@ EXAMPLE_LIST=" decode_audio_example decode_video_example demuxing_decoding_example + device_get_capabilities_example encode_audio_example encode_video_example extract_mvs_example @@ -3751,6 +3752,7 @@ avio_reading_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" decode_video_example_deps="avcodec avutil" demuxing_decoding_example_deps="avcodec avformat avutil" +device_get_capabilities_example_deps="avdevice avformat avutil" encode_audio_example_deps="avcodec avutil" encode_video_example_deps="avcodec avutil" extract_mvs_example_deps="avcodec avformat avutil" diff --git a/doc/examples/.gitignore b/doc/examples/.gitignore index 44960e1de7..256f33a600 100644 --- a/doc/examples/.gitignore +++ b/doc/examples/.gitignore @@ -3,6 +3,7 @@ /decode_audio /decode_video /demuxing_decoding +/device_get_capabilities /encode_audio /encode_video /extract_mvs diff --git a/doc/examples/Makefile b/doc/examples/Makefile index 81bfd34d5d..de707bb3ca 100644 --- a/doc/examples/Makefile +++ b/doc/examples/Makefile @@ -3,6 +3,7 @@ EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video EXAMPLES-$(CONFIG_DEMUXING_DECODING_EXAMPLE) += demuxing_decoding +EXAMPLES-$(CONFIG_DEVICE_GET_CAPABILITIES_EXAMPLE) += device_get_capabilities EXAMPLES-$(CONFIG_ENCODE_AUDIO_EXAMPLE) += encode_audio EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs diff --git a/doc/examples/Makefile.example b/doc/examples/Makefile.example index a232d97f98..b861b9cc74 100644 --- a/doc/examples/Makefile.example +++ b/doc/examples/Makefile.example @@ -16,6 +16,7 @@ EXAMPLES= avio_list_dir \ decode_audio \ decode_video \ demuxing_decoding \ + device_get_capabilities \ encode_audio \ encode_video \ extract_mvs \ diff --git a/doc/examples/device_get_capabilities.c b/doc/examples/device_get_capabilities.c new file mode 100644 index 0000000000..45eb2eadf4 --- /dev/null +++ b/doc/examples/device_get_capabilities.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2021 Diederick Niehorster + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @file + * avdevice getting capabilities example. + * + * Shows how to use the avdevice capabilities API to probe + * device capabilities (supported codecs, pixel formats, sample + * formats, resolutions, channel counts, etc) + * @example device_get_capabilities.c + */ + +#include <libavformat/avformat.h> +#include <libavdevice/avdevice.h> +#include <libavutil/avstring.h> +#include <libavutil/log.h> +#include <libavutil/bprint.h> + +int print_option_ranges(enum AVOptionType type, AVOptionRanges *ranges) +{ + for (int range_index = 0; range_index < ranges->nb_ranges; range_index++) { + int ret; + char *out_val = NULL; + AVBPrint bp; + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); + for (int component_index = 0; component_index < ranges->nb_components; component_index++) + { + AVOptionRange* range = ranges->range[ranges->nb_ranges * component_index + range_index]; + if (component_index > 0) + av_bprintf(&bp, ", "); + av_bprintf(&bp, "%s: ", range->str); + if (range->value_min > range->value_max) + av_bprintf(&bp, "<value not available>"); + else { + avdevice_capabilities_bprint_num(&bp, range->str, range->value_min); + if (range->is_range) { + av_bprintf(&bp, " -- "); + avdevice_capabilities_bprint_num(&bp, range->str, range->value_max); + } + } + } + if (!av_bprint_is_complete(&bp)) + return AVERROR(ENOMEM); + if ((ret = av_bprint_finalize(&bp, &out_val)) < 0) + return ret; + printf("%s\n", out_val); + av_freep(&out_val); + } + + return 0; +} + +void list_queries() +{ + const AVOption *opt = NULL; + const AVClass *class = avdevice_capabilities_get_class(); + while (opt = av_opt_next(&class, opt)) + fprintf(stderr, " %s\n", opt->name); +} + +void list_device_sources(const AVInputFormat *fmt) +{ + int ret; + AVDeviceInfoList *device_list = NULL; + + if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) + return; + + if (!fmt->get_device_list) { + ret = AVERROR(ENOSYS); + fprintf(stderr, " Cannot list sources. Not implemented.\n"); + return; + } + + if ((ret = avdevice_list_input_sources(fmt, NULL, NULL, &device_list)) < 0) { + fprintf(stderr, " Cannot list sources.\n"); + return; + } + + for (int i = 0; i < device_list->nb_devices; i++) { + const AVDeviceInfo *device = device_list->devices[i]; + fprintf(stderr, " %s %s (", device_list->default_device == i ? "*" : " ", device->device_name); + if (device->nb_media_types > 0 && device->media_types) { + for (int j = 0; j < device->nb_media_types; ++j) { + const char* media_type = av_get_media_type_string(device->media_types[j]); + if (j > 0) + fprintf(stderr, ", "); + fprintf(stderr, "%s", media_type ? media_type : "unknown"); + } + } + else { + fprintf(stderr, "none"); + } + fprintf(stderr, ")\n"); + } + + avdevice_free_list_devices(&device_list); +} + + + +int main (int argc, char **argv) +{ + int ret = 0; + const char *device_name = NULL; + const char *input_name = NULL; + const char *query_cap = NULL; + const char *set_cap_name = NULL; + const char *set_cap_value = NULL; + + const AVInputFormat *fmt = NULL; + AVFormatContext *fmt_ctx = NULL; + AVDeviceCapabilitiesQuery *caps = NULL; + AVOptionRanges *ranges = NULL; + const AVOption *opt = NULL; + + if (argc != 6) { + fprintf(stderr, "usage: %s device_name input_name query_cap set_cap_name set_cap_value\n" + "API example program to show how to use the avdevice\n" + "capabilities API to probe device capabilities \n" + "(supported codecs, pixel formats, sample formats,\n" + "resolutions, channel counts, etc).\n\n" + "example invocation: " + "%s dshow video=\"Integrated Webcam\" frame_size pixel_format yuyv422", + argv[0], argv[0]); + exit(1); + } + device_name = argv[1]; + input_name = argv[2]; + query_cap = argv[3]; + set_cap_name = argv[4]; + set_cap_value = argv[5]; + + // make sure avdevices can be found among input and output formats + avdevice_register_all(); + // find specified device + fmt = av_find_input_format(device_name); + if (!fmt) { + fprintf(stderr, "Could not find the device '%s'\n",device_name); + ret = AVERROR(EINVAL); + goto end; + } + + // prepare device format context, and set device to query, + ret = avformat_alloc_input_context(&fmt_ctx, fmt, NULL); + if (ret < 0) { + fprintf(stderr, "Cannot allocate input format context\n"); + goto end; + } + fmt_ctx->url = av_strdup(input_name); + + // prepare query object, setting device options + ret = avdevice_capabilities_create(&caps, fmt_ctx, NULL); + if (ret < 0) { + fprintf(stderr, "avdevice_capabilities_create() failed. Possibly the input name you specified ('%s') is not available for this device ('%s').\n%s can access the following sources:\n", input_name, device_name, device_name); + list_device_sources(fmt); + goto end; + } + + // check capability to query, and get info about the return type + opt = av_opt_find(caps, query_cap, NULL, 0, 0); + if (!opt) { + fprintf(stderr, "Capability '%s' you wish to query is not available.\nYou can query the following capabilities:\n", query_cap); + list_queries(); + ret = AVERROR_OPTION_NOT_FOUND; + goto end; + } + + // query the capability without any filter set + ret = av_opt_query_ranges(&ranges, caps, opt->name, AV_OPT_MULTI_COMPONENT_RANGE); + if (ret < 0) { + fprintf(stderr, "av_opt_query_ranges() failed\n"); + goto end; + } + + // print results + ret = print_option_ranges(opt->type, ranges); + if (ret < 0) { + fprintf(stderr, "printing the AVOptionRanges failed\n"); + goto end; + } + av_opt_freep_ranges(&ranges); + + printf("=============\n"); + + // set one capability, which may filter out some returned capabilities + // (or all, if set to an invalid value) + ret = av_opt_set(caps, set_cap_name, set_cap_value, 0); + if (ret < 0) { + fprintf(stderr, "av_opt_set() failed when trying to set the capability '%s'. Possibly it is not available.\nYou can set the following capabilities:\n", set_cap_name); + list_queries(); + goto end; + } + + // query again + ret = av_opt_query_ranges(&ranges, caps, opt->name, AV_OPT_MULTI_COMPONENT_RANGE); + if (ret < 0) { + fprintf(stderr, "av_opt_query_ranges() failed\n"); + goto end; + } + + // print results + print_option_ranges(opt->type, ranges); + + +end: + if (ranges) + av_opt_freep_ranges(&ranges); + if (caps) + avdevice_capabilities_free(&caps, fmt_ctx); + + if (fmt_ctx) + avformat_free_context(fmt_ctx); + + if (ret < 0) { + char a[AV_ERROR_MAX_STRING_SIZE] = { 0 }; + av_make_error_string(a, AV_ERROR_MAX_STRING_SIZE, ret); + + printf("Error: %s\n", a); + } + + return ret < 0; +} diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 5f9dfccc34..c29d8940a5 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -384,38 +384,7 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, * For example, setting a codec may impact number of formats or fps values * returned during next query. Setting invalid value may limit results to zero. * - * Example of the usage basing on opengl output device: - * - * @code - * AVFormatContext *oc = NULL; - * AVDeviceCapabilitiesQuery *caps = NULL; - * AVOptionRanges *ranges; - * int ret; - * - * if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0) - * goto fail; - * if (avdevice_capabilities_create(&caps, oc, NULL) < 0) - * goto fail; - * - * //query codecs - * if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0) - * goto fail; - * //pick codec here and set it - * av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0); - * - * //query format - * if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0) - * goto fail; - * //pick format here and set it - * av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0); - * - * //query and set more capabilities - * - * fail: - * //clean up code - * avdevice_capabilities_free(&query, oc); - * avformat_free_context(oc); - * @endcode + * @see examples/device_get_capabilities.c */ typedef struct AVDeviceCapabilitiesQuery AVDeviceCapabilitiesQuery; -- 2.28.0.windows.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-03-25 14:15 UTC|newest] Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-03-25 14:10 [FFmpeg-devel] [PATCH v4 00/22] avdevice (mostly dshow) enhancements Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 01/22] avdevice/dshow: fix regression Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 02/22] avdevice: lock to minor version of avformat Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 03/22] avformat: add control_message function to AVInputFormat Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 04/22] avdevice/dshow: implement control_message interface Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 05/22] avdevice: add control message requesting to show config dialog Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 06/22] avdevice/dshow: accept show config dialog control message Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 07/22] avdevice/dshow: add config dialog command for crossbar and tv tuner Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 08/22] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API" Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 09/22] avdevice/avdevice: clean up avdevice_capabilities_create Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 10/22] avdevice: capabilities API details no longer public Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 11/22] avutil/opt: document AVOptionRange min_value > max_value Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 12/22] avdevice: Add internal helpers for querying device capabilities Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 13/22] avdevice: change device capabilities option type Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 14/22] avdevice: improve capabilities' option API Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 15/22] avdevice/dshow: move audio format helpers Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 16/22] avdevice/dshow: when closing, set context fields back to zero Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 17/22] avdevice/dshow: implement capabilities API Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 18/22] avdevice/dshow: cosmetics Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 19/22] avformat: add avformat_alloc_input_context() Diederick Niehorster 2022-03-25 14:10 ` Diederick Niehorster [this message] 2022-03-25 17:26 ` [FFmpeg-devel] [PATCH v4 20/22] doc/examples: adding device_get_capabilities example Michael Niedermayer 2022-03-25 21:19 ` Diederick C. Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 21/22] Makefile/examples: cosmetics Diederick Niehorster 2022-03-25 14:10 ` [FFmpeg-devel] [PATCH v4 22/22] avdevice/dshow: capabilities query also works on opened device Diederick Niehorster 2022-03-29 3:59 ` [FFmpeg-devel] [PATCH v4 00/22] avdevice (mostly dshow) enhancements Roger Pack
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220325141041.1748-21-dcnieho@gmail.com \ --to=dcnieho@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git