[FFmpeg-devel] [PATCH 1/4] lavf: add probe device API

Lukasz M lukasz.m.luki at gmail.com
Wed Dec 4 17:30:57 CET 2013


On 25 November 2013 17:30, wm4 <nfxjfg at googlemail.com> wrote:

> 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.
>

But how you want to keep backward compatibility when you move it somewhere
else?
I'd like to develop devices, but some decisions about that would be great.
I'm finishing opengl device which I want to use and I will have to extend
API to make it useful.
Personally I don't mind submitting everything to open source, but without
API extension I will sooner or later finish with my own fork.


More information about the ffmpeg-devel mailing list