Diederick Niehorster: > Signed-off-by: Diederick Niehorster <dcni...@gmail.com> > --- > configure | 2 + > doc/examples/.gitignore | 1 + > doc/examples/Makefile | 47 ++++---- > doc/examples/Makefile.example | 1 + > doc/examples/device_get_capabilities.c | 151 +++++++++++++++++++++++++ > 5 files changed, 179 insertions(+), 23 deletions(-) > create mode 100644 doc/examples/device_get_capabilities.c > > diff --git a/configure b/configure > index 82367fd30d..5e9666d017 100755 > --- a/configure > +++ b/configure > @@ -1705,6 +1705,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 > @@ -3712,6 +3713,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..7988ed4226 100644 > --- a/doc/examples/Makefile > +++ b/doc/examples/Makefile > @@ -1,26 +1,27 @@ > -EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir > -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_ENCODE_AUDIO_EXAMPLE) += encode_audio > -EXAMPLES-$(CONFIG_ENCODE_VIDEO_EXAMPLE) += encode_video > -EXAMPLES-$(CONFIG_EXTRACT_MVS_EXAMPLE) += extract_mvs > -EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio > -EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio > -EXAMPLES-$(CONFIG_FILTERING_VIDEO_EXAMPLE) += filtering_video > -EXAMPLES-$(CONFIG_HTTP_MULTICLIENT_EXAMPLE) += http_multiclient > -EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode > -EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata > -EXAMPLES-$(CONFIG_MUXING_EXAMPLE) += muxing > -EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec > -EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing > -EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio > -EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video > -EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac > -EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding > -EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode > -EXAMPLES-$(CONFIG_VAAPI_TRANSCODE_EXAMPLE) += vaapi_transcode > +EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir > +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 > +EXAMPLES-$(CONFIG_FILTER_AUDIO_EXAMPLE) += filter_audio > +EXAMPLES-$(CONFIG_FILTERING_AUDIO_EXAMPLE) += filtering_audio > +EXAMPLES-$(CONFIG_FILTERING_VIDEO_EXAMPLE) += filtering_video > +EXAMPLES-$(CONFIG_HTTP_MULTICLIENT_EXAMPLE) += http_multiclient > +EXAMPLES-$(CONFIG_HW_DECODE_EXAMPLE) += hw_decode > +EXAMPLES-$(CONFIG_METADATA_EXAMPLE) += metadata > +EXAMPLES-$(CONFIG_MUXING_EXAMPLE) += muxing > +EXAMPLES-$(CONFIG_QSVDEC_EXAMPLE) += qsvdec > +EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing > +EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio > +EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video > +EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac > +EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding > +EXAMPLES-$(CONFIG_VAAPI_ENCODE_EXAMPLE) += vaapi_encode > +EXAMPLES-$(CONFIG_VAAPI_TRANSCODE_EXAMPLE) += vaapi_transcode >
Moving everything to the right should be done in a separate commit (if at all). > EXAMPLES := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF)) > EXAMPLES_G := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)_g$(EXESUF)) > 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..f3b9f31e0d > --- /dev/null > +++ b/doc/examples/device_get_capabilities.c > @@ -0,0 +1,151 @@ > +/* > + * 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 <libavdevice/avdevice.h> > +#include <libavutil/avstring.h> > +#include <libavformat/avformat.h> > +#include <libavutil/log.h> > + > + > + > +int main (int argc, char **argv) > +{ > + int ret = 0; > + const char* dshow_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; > + > + if (argc != 5) { > + fprintf(stderr, "usage: %s dshow_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 video=\"Integrated Webcam\" frame_size pixel_format > yuyv422", > + argv[0], argv[0]); > + exit(1); > + } > + dshow_input_name = argv[1]; > + query_cap = argv[2]; > + set_cap_name = argv[3]; > + set_cap_value = argv[4]; > + > + // make sure avdevices can be found > + avdevice_register_all(); > + // find our device (capabilities API is currently > + // only implemented for dshow device, so hardcode that) This information is internal and does not belong into an example; the best way is probably to set the device type via a new argument. > + fmt = av_find_input_format("dshow"); Missing check for fmt (e.g. dshow is unavailable if not on Windows). > + > + // since there is no equivalent of avformat_alloc_output_context2 for an > input context, > + // so we get this dirty code that users shouldn't have to write.... > + fmt_ctx = avformat_alloc_context(); > + fmt_ctx->url = av_strdup(dshow_input_name); Missing checks. > + fmt_ctx->iformat = fmt; > + if (fmt_ctx->iformat->priv_data_size > 0) { priv_data_size is not part of the public API; so the code is indeed dirty and so this example is unacceptable as-is. This might be a scenario where AVFMT_FLAG_PRIV_OPT might have been useful, see 2ff40b98ecbd9befadddc8fe665a391f99bfca32. > + if (!(fmt_ctx->priv_data = > av_mallocz(fmt_ctx->iformat->priv_data_size))) { > + ret = AVERROR(ENOMEM); > + goto end; > + } > + if (fmt_ctx->iformat->priv_class) { > + *(const AVClass**)fmt_ctx->priv_data = > fmt_ctx->iformat->priv_class; > + av_opt_set_defaults(fmt_ctx->priv_data); > + } > + } > + // end dirty code > + > + // query the capability without any filter set > + ret = avdevice_capabilities_create(&caps, fmt_ctx, NULL); > + if (ret < 0) > + goto end; > + > + ret = av_opt_query_ranges(&ranges, caps, query_cap, > AV_OPT_MULTI_COMPONENT_RANGE); > + if (ret < 0) > + goto end; > + > + for (int range_index = 0; range_index < ranges->nb_ranges; > range_index++) { > + 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) > + printf(", "); > + printf("%s: %.2f -- %.2f", range->str, range->value_min, > range->value_max); > + } > + printf("\n"); > + } > + 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) > + goto end; > + > + ret = av_opt_query_ranges(&ranges, caps, query_cap, > AV_OPT_MULTI_COMPONENT_RANGE); > + if (ret < 0) > + goto end; > + > + for (int range_index = 0; range_index < ranges->nb_ranges; > range_index++) { > + 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) > + printf(", "); > + printf("%s: %.2f -- %.2f", range->str, range->value_min, > range->value_max); > + } > + printf("\n"); > + } > + > + > +end: > + av_opt_freep_ranges(&ranges); > + avdevice_capabilities_free(&caps, fmt_ctx); > + > + avformat_close_input(&fmt_ctx); avformat_close_input() may only be used if you have used avformat_open_input(); otherwise one has to use avformat_free_context(). > + > + 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; > +} > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".