[FFmpeg-devel] [PATCH 1/4] lavf: add probe device API
Lukasz Marek
lukasz.m.luki at gmail.com
Tue Nov 12 00:11:59 CET 2013
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
--
1.7.10.4
More information about the ffmpeg-devel
mailing list