[FFmpeg-devel] [PATCH 1/4] lavf: add probe device API
wm4
nfxjfg at googlemail.com
Mon Nov 25 17:30:53 CET 2013
On Tue, 12 Nov 2013 00:11:59 +0100
Lukasz Marek <lukasz.m.luki at gmail.com> wrote:
> Adds new API dedicated for output devices.
>
> This API allows to
> - Test device with provided configuration
> Audio devices params:
> - device name
> - codec
> - sample format
> - channel count
> - channels layout
> - sample rate
> Video devices params:
> - device name
> - codec
> - pixel format
> - width (minimal width as input and real width as output)
> - height (minimal height as input and real height as output)
>
> - Get all supported configurations matching provided filter.
> Filter may contain any subset of Audio/Video device params.
>
> Behaviour of probe function can also be modified by flags.
>
> Signed-off-by: Lukasz Marek <lukasz.m.luki at gmail.com>
> ---
> libavformat/avformat.h | 97 +++++++++++++++++++++++++++++++++++++++++++++++-
> libavformat/utils.c | 72 +++++++++++++++++++++++++++++++++++
> 2 files changed, 167 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 6bd54ce..68b9269 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -323,6 +323,28 @@ typedef struct AVFrac {
> int64_t val, num, den;
> } AVFrac;
>
> +/**
> + *
> + */
> +typedef struct AVDeviceConfig {
> + struct AVDeviceConfig *next;
> + char* device_name; ///< device name, format depends on device
> + char* device_description; ///< human friendly name
> + enum AVCodecID codec; ///< codec
> + int format; ///< format (AVPixelFormat / AVSampleFormat)
> + union {
> + struct { // audio parameters
> + int sample_rate; ///< [in]: expected sample rate, [out]: device's default sample rate
> + int channels; ///< [in]: expected channel count, [out]: device's default channel count
> + int64_t channel_layout; ///< [in]: expected layout, [out]: device's default layout
> + };
> + struct { // video parameters
> + int width; ///< [in]: required width, [out]: maximum width
> + int height; ///< [in]: required height, [out]: maximum height
> + };
> + } stream_info;
> +} AVDeviceConfig;
> +
> /*************************************************/
> /* input/output formats */
>
> @@ -379,6 +401,14 @@ typedef struct AVProbeData {
>
> #define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */
>
> +#define AV_PROBEDEV_DEFAULT_DEV 0x0001 /**< Probe default device only */
> +#define AV_PROBEDEV_RAW_DATA 0x0002 /**< Return only raw codecs: AV_CODEC_ID_PCM_*,
> + AV_CODEC_ID_RAWVIDEO */
> +#define AV_PROBEDEV_ALLOW_STREAM_PARAM_CHANGES 0x0004 /**< Allow modification of wanted stream
> + parameteres when provided value is not supported.
> + Video devices will update width and height for
> + screen resolution. */
> +
> /**
> * @addtogroup lavf_encoding
> * @{
> @@ -453,6 +483,11 @@ typedef struct AVOutputFormat {
>
> void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
> int64_t *dts, int64_t *wall);
> +
> + /**
> + * Probe device. See avformat_probe_device() for more details.
> + */
> + AVDeviceConfig* (*probe_device)(AVDeviceConfig *wanted, int flags, AVDictionary *opts);
> } AVOutputFormat;
> /**
> * @}
> @@ -1954,7 +1989,6 @@ enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
> int av_get_output_timestamp(struct AVFormatContext *s, int stream,
> int64_t *dts, int64_t *wall);
>
> -
> /**
> * @}
> */
> @@ -2164,6 +2198,66 @@ int av_match_ext(const char *filename, const char *extensions);
> int avformat_query_codec(AVOutputFormat *ofmt, enum AVCodecID codec_id, int std_compliance);
>
> /**
> + * Probe device and return all valid configurations that are working on hardware.
> + *
> + * Some audio device system may use any sample rate and channel count.
> + * Audio devices will not return all possible stream parameters (sample rate, channel count/layout),
> + * but will return all device names and all codec/format pairs.
> + * Stream parameters will be copied from wanted configuration or default device values will
> + * be used when no wanted value specified.
> + * Stream defaults will also be copied from default device values when provided
> + * configuration is invalid and AV_PROBEDEV_ALLOW_STREAM_PARAM_CHANGES flag is set.
> + *
> + * Video devices will return all devices that fulfill wanted configuration.
> + * They will set width/height with screen resolution when AV_PROBEDEV_ALLOW_STREAM_PARAM_CHANGES flag is set.
> + *
> + * When AV_PROBEDEV_DEFAULT_DEV flag is provided then only default device is returned.
> + * This flag has precedence over devices requested by wanted configuration or options.
> + * When default device cannot be determined, then random one device is returned.
> + *
> + * When AV_PROBEDEV_RAW_DATA flag is provided then only raw codec will be returned.
> + * It is supposed to be useful when filters are used.
> + *
> + * @param ofmt output device context.
> + * @param[out] valid all valid configurations or NULL when no valid configuration detected.
> + * Returned value must be freed with avformat_free_device_config().
> + * @param wanted expected configuration. May be NULL or not fully filled.
> + * @param flags combination of AV_PROBE_DEVICE_*.
> + * @param opts device options. Meaning of options is device dependent.
> + * If any option is also available in wanted configuration then wanted
> + * configuration has precedence.
> + * @return 0 on success, negative otherwise.
> + * @note AVERROR_PATCHWELCOME is returned when device doesn't implement this function.
> + * In this case, negative result doesn't mean tested configuration is invalid.
> + */
> +int avformat_probe_device(AVOutputFormat *ofmt, AVDeviceConfig **valid,
> + AVDeviceConfig *wanted, int flags, AVDictionary *opts);
> +
> +/**
> + * Free device configuration and its internal data.
> + *
> + * @param config data to be freed.
> + */
> +void avformat_free_device_config(AVDeviceConfig **config);
> +
> +/**
> + * Initialize configuration with default values.
> + *
> + * @param config configuration to initialize.
> + *
> + * @note Function doesn't free internal data.
> + */
> +void avformat_device_config_defaults(AVDeviceConfig *config);
> +
> +/**
> + * Copy device configuration.
> + *
> + * @param config configuration to be copied.
> + * @return deep copy of device configuration.
> + */
> +AVDeviceConfig* avformat_copy_device_config(AVDeviceConfig* config);
> +
> +/**
> * @defgroup riff_fourcc RIFF FourCCs
> * @{
> * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are
> @@ -2235,7 +2329,6 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
>
> int avformat_queue_attached_pictures(AVFormatContext *s);
>
> -
> /**
> * @}
> */
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index f02312f..d71e9ad 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -4008,6 +4008,78 @@ int avformat_query_codec(AVOutputFormat *ofmt, enum AVCodecID codec_id, int std_
> return AVERROR_PATCHWELCOME;
> }
>
> +int avformat_probe_device(AVOutputFormat *ofmt, AVDeviceConfig **valid,
> + AVDeviceConfig *wanted, int flags, AVDictionary *opts)
> +{
> + if (!valid)
> + return -1;
> + *valid = NULL;
> + if (!ofmt)
> + return -1;
> + if (!ofmt->probe_device)
> + return AVERROR_PATCHWELCOME;
> +
> + if (wanted && wanted->codec != AV_CODEC_ID_NONE && wanted->format != -1) {
> + int i;
> + AVCodec *codec = avcodec_find_encoder(wanted->codec);
> + if (!codec)
> + return -1;
> + if (codec->sample_fmts)
> + for (i = 0;; i++) {
> + if (wanted->format == codec->sample_fmts[i])
> + break;
> + if (codec->sample_fmts[i] == -1)
> + return -1;
> + }
> + if (codec->pix_fmts)
> + for (i = 0;; i++) {
> + if (wanted->format == codec->pix_fmts[i])
> + break;
> + if (codec->pix_fmts[i] == -1)
> + return -1;
> + }
> + }
> +
> + *valid = ofmt->probe_device(wanted, flags, opts);
> + return 0;
> +}
> +
> +void avformat_free_device_config(AVDeviceConfig **config)
> +{
> + AVDeviceConfig *current, *next;
> + if (!config)
> + return;
> +
> + next = *config;
> + while (next) {
> + current = next;
> + next = current->next;
> + av_free(current->device_name);
> + av_free(current->device_description);
> + av_free(current);
> + }
> + *config = NULL;
> +}
> +
> +void avformat_device_config_defaults(AVDeviceConfig *config)
> +{
> + if (!config)
> + return;
> + memset(config, 0, sizeof(AVDeviceConfig));
> + config->format = -1; /* AV_PIX_FMT_NONE or AV_SAMPLE_FMT_NONE */
> +}
> +
> +AVDeviceConfig* avformat_copy_device_config(AVDeviceConfig* config)
> +{
> + AVDeviceConfig *copy = av_memdup(config, sizeof(AVDeviceConfig));
> + if (copy) {
> + copy->next = NULL;
> + copy->device_name = av_strdup(config->device_name);
> + copy->device_description = av_strdup(config->device_description);
> + }
> + return copy;
> +}
> +
> int avformat_network_init(void)
> {
> #if CONFIG_NETWORK
Has anyone thought of the idea that the (de)muxer API is maybe not the
best way to handle I/O devices? I think even messing it into
libavfilter might make more sense. Or making a new API.
More information about the ffmpeg-devel
mailing list