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

Michael Niedermayer michaelni at gmx.at
Thu Dec 5 00:55:11 CET 2013


On Wed, Dec 04, 2013 at 05:30:57PM +0100, Lukasz M wrote:
> 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.

if someone posts a patch that extends the API and that is needed for
some also posted device code.
and noone else comes up with a better patch and the patch has no ABI
issues (future extendbility, compatibility for example) and noone has
major objections then ill apply it.


> 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.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20131205/b1f788e8/attachment.asc>


More information about the ffmpeg-devel mailing list