[FFmpeg-devel] [PATCH 4/4] examples: adding device_get_capabilities example
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Sat Jun 5 09:51:26 EEST 2021
Diederick Niehorster:
> Signed-off-by: Diederick Niehorster <dcnieho at 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;
> +}
>
More information about the ffmpeg-devel
mailing list