* [FFmpeg-devel] [PATCH v5 01/21] avdevice: lock to minor version of avformat
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 02/21] avformat: add control_message function to AVInputFormat Diederick Niehorster
` (20 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
As per discussion on the list (
https://ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281513.html, see
especially https://ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281586.html),
to resolve the the unholy ABI-relationship between libavdevice and
libavformat and allow easier working on the part of the avdevice API
that lives in avformat, lock avdevice to a specific major and minor
version of avformat.
Documentation of this restriction added.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 13 +++++++++++++
libavdevice/avdevice.h | 10 ++++++++++
libavdevice/version.h | 13 ++++++++++++-
libavformat/avformat.h | 3 +++
libavformat/utils.c | 5 +++++
libavformat/version.h | 14 ++++++++++++--
libavutil/avutil.h | 3 +++
libavutil/macros.h | 3 +++
8 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 833d200054..98934abfb7 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -19,6 +19,7 @@
#include "libavutil/avassert.h"
#include "libavutil/samplefmt.h"
#include "libavutil/pixfmt.h"
+#include "libavformat/version.h"
#include "avdevice.h"
#include "internal.h"
#include "config.h"
@@ -39,6 +40,18 @@ unsigned avdevice_version(void)
return LIBAVDEVICE_VERSION_INT;
}
+unsigned avdevice_version_same_minor(void)
+{
+ // check version of loaded lavf has same major and minor version as
+ // this library was compiled against
+ // NB: this function doesn't have to be called, dynamic linker will
+ // signal error when avformat of wrong major or minor version is found.
+ if ((avformat_version_same_minor()) & ~0xFF != (LIBAVFORMAT_VERSION_INT & ~0xFF))
+ abort();
+
+ return avdevice_version();
+}
+
const char * avdevice_configuration(void)
{
return FFMPEG_CONFIGURATION;
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index 0b32e59fed..db16a2f27e 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -47,6 +47,16 @@
*
* To use libavdevice, simply call avdevice_register_all() to register all
* compiled muxers and demuxers. They all use standard libavformat API.
+ *
+ * Note that libavdevice is locked to be used with the same major and minor
+ * version of libavformat that it was built against. Attempting to use a
+ * shared build of FFmpeg or its libavdevice library with a libavformat of
+ * a different major or minor version will generate a dynamic linker error.
+ * This is achieved by the internal function check_avformat_same_minor() in
+ * avdevice.c. This function does not have to be called, its call to
+ * avformat_version_same_minor() (a macro which expands to a name with the
+ * specific major and minor version of avformat embedded in it) is sufficient
+ * to trigger link failure.
*
* @{
*/
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 09c1d778dc..4efe7f8649 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -26,10 +26,11 @@
*/
#include "libavutil/version.h"
+#include "libavutil/macros.h"
#include "version_major.h"
-#define LIBAVDEVICE_VERSION_MINOR 6
+#define LIBAVDEVICE_VERSION_MINOR 7
#define LIBAVDEVICE_VERSION_MICRO 100
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
@@ -42,4 +43,14 @@
#define LIBAVDEVICE_IDENT "Lavd" AV_STRINGIFY(LIBAVDEVICE_VERSION)
+/**
+ * avdevice_version_same_minor() expands to a function with
+ * the same minor and major version it was compiled against
+ * encoded in it. Enables locking to the minor version of
+ * other libraries they were compiled against. Does not have
+ * to be called by user.
+ */
+#define avdevice_version_same_minor AV_MAKE_MAJOR_MINOR_FUNC_NAME(device,LIBAVFORMAT_VERSION_MAJOR,LIBAVFORMAT_VERSION_MINOR)
+unsigned avdevice_version_same_minor(void);
+
#endif /* AVDEVICE_VERSION_H */
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index f12fa7d904..350912e272 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -64,6 +64,9 @@
* set by user for input, always set by user for output (unless you are dealing
* with an AVFMT_NOFILE format).
*
+ * Note that libavdevice is locked to a specific major and minor version of
+ * libavformat, see @ref lavd "libavdevice" for more details.
+ *
* @section lavf_options Passing options to (de)muxers
* It is possible to configure lavf muxers and demuxers using the @ref avoptions
* mechanism. Generic (format-independent) libavformat options are provided by
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 3f253c2045..6d9c4e778a 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -64,6 +64,11 @@ unsigned avformat_version(void)
return LIBAVFORMAT_VERSION_INT;
}
+unsigned avformat_version_same_minor(void)
+{
+ return avformat_version();
+}
+
const char *avformat_configuration(void)
{
return FFMPEG_CONFIGURATION;
diff --git a/libavformat/version.h b/libavformat/version.h
index f4a26c2870..bb6a7d4510 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -28,11 +28,12 @@
*/
#include "libavutil/version.h"
+#include "libavutil/macros.h"
#include "version_major.h"
-#define LIBAVFORMAT_VERSION_MINOR 20
-#define LIBAVFORMAT_VERSION_MICRO 101
+#define LIBAVFORMAT_VERSION_MINOR 21
+#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
@@ -44,4 +45,13 @@
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
+/**
+ * avformat_version_same_minor() expands to a function with
+ * the same minor and major version it was compiled against
+ * encoded in it. Enables locking to the minor version of
+ * other libraries they were compiled against.
+ */
+#define avformat_version_same_minor AV_MAKE_MAJOR_MINOR_FUNC_NAME(format,LIBAVFORMAT_VERSION_MAJOR,LIBAVFORMAT_VERSION_MINOR)
+unsigned avformat_version_same_minor(void);
+
#endif /* AVFORMAT_VERSION_H */
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index 4d633156d1..94ce472c27 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -76,6 +76,9 @@
* situations may change slightly (and be documented). All those are accompanied
* by an entry in doc/APIchanges and incrementing either the minor or micro
* version number.
+ *
+ * Note that libavdevice is locked to a specific major and minor version of
+ * libavformat, see @ref lavd "libavdevice" for more details.
*/
/**
diff --git a/libavutil/macros.h b/libavutil/macros.h
index 2a7567c3ea..dab530a8a0 100644
--- a/libavutil/macros.h
+++ b/libavutil/macros.h
@@ -73,6 +73,9 @@
* @}
*/
+#define AV_MAKE_MAJOR_MINOR_FUNC_NAME_IMPL(name,major,minor) av ## name ## _version_ ## major ## _ ## minor
+#define AV_MAKE_MAJOR_MINOR_FUNC_NAME(name,major,minor) AV_MAKE_MAJOR_MINOR_FUNC_NAME_IMPL(name,major,minor)
+
#define AV_PRAGMA(s) _Pragma(#s)
#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 02/21] avformat: add control_message function to AVInputFormat
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 01/21] avdevice: lock to minor version of avformat Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 03/21] avdevice/dshow: implement control_message interface Diederick Niehorster
` (19 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Control messages are useful for programmatic control of not only outdevs
but also indevs.
Bumping avformat version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 8 +++++---
libavformat/avformat.h | 6 ++++++
libavformat/version.h | 2 +-
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 98934abfb7..43d3406670 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -66,9 +66,11 @@ const char * avdevice_license(void)
int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type,
void *data, size_t data_size)
{
- if (!s->oformat || !s->oformat->control_message)
- return AVERROR(ENOSYS);
- return s->oformat->control_message(s, type, data, data_size);
+ if (s->oformat && s->oformat->control_message)
+ return s->oformat->control_message(s, type, data, data_size);
+ if (s->iformat && s->iformat->control_message)
+ return s->iformat->control_message(s, type, data, data_size);
+ return AVERROR(ENOSYS);
}
int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type,
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 350912e272..06db024559 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -785,6 +785,12 @@ typedef struct AVInputFormat {
*/
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
+ /**
+ * Allows sending messages from application to device.
+ */
+ int (*control_message)(struct AVFormatContext *s, int type,
+ void *data, size_t data_size);
+
/**
* Returns device list with it properties.
* @see avdevice_list_devices() for more details.
diff --git a/libavformat/version.h b/libavformat/version.h
index bb6a7d4510..d195704a31 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
#include "version_major.h"
-#define LIBAVFORMAT_VERSION_MINOR 21
+#define LIBAVFORMAT_VERSION_MINOR 22
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 03/21] avdevice/dshow: implement control_message interface
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 01/21] avdevice: lock to minor version of avformat Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 02/21] avformat: add control_message function to AVInputFormat Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 04/21] avdevice: add control message requesting to show config dialog Diederick Niehorster
` (18 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
This allows programmatic users of avdevice to start and stop the
DirectShow Capture graph (i.e. receive frames or not). This is important
because now the buffer fills up and starts dropping samples when
enqueued packets are not read out immediately after the demuxer is
opened.
Bumping avdevice version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 42 +++++++++++++++++++++++++++++++++++++
libavdevice/dshow_capture.h | 1 +
libavdevice/version.h | 2 +-
3 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index abb8325bc3..652e093204 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -1503,6 +1503,45 @@ error:
return ret;
}
+static int dshow_control_message(AVFormatContext *avctx, int type, void *data, size_t data_size)
+{
+ struct dshow_ctx *ctx = avctx->priv_data;
+ int run_state = ctx->is_running;
+ HRESULT hr;
+
+ switch (type) {
+ case AV_APP_TO_DEV_PAUSE:
+ run_state = 0;
+ break;
+ case AV_APP_TO_DEV_PLAY:
+ run_state = 1;
+ break;
+ case AV_APP_TO_DEV_TOGGLE_PAUSE:
+ run_state = !run_state;
+ break;
+ }
+
+ // if play state change requested, apply
+ if (run_state != ctx->is_running) {
+ if (run_state)
+ hr = IMediaControl_Run(ctx->control);
+ else
+ hr = IMediaControl_Pause(ctx->control);
+
+ if (hr == S_FALSE) {
+ OAFilterState pfs;
+ hr = IMediaControl_GetState(ctx->control, 0, &pfs);
+ }
+ if (hr != S_OK) {
+ av_log(avctx, AV_LOG_ERROR, "Could not run/pause graph\n");
+ return AVERROR(EIO);
+ }
+ ctx->is_running = run_state;
+ }
+
+ return 0;
+}
+
static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
{
switch (sample_fmt) {
@@ -1747,6 +1786,7 @@ static int dshow_read_header(AVFormatContext *avctx)
}
// don't exit yet, allow it to list crossbar options in dshow_open_device
}
+ ctx->is_running = 0;
if (ctx->device_name[VideoDevice]) {
if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 ||
(r = dshow_add_device(avctx, VideoDevice)) < 0) {
@@ -1820,6 +1860,7 @@ static int dshow_read_header(AVFormatContext *avctx)
av_log(avctx, AV_LOG_ERROR, "Could not run graph (sometimes caused by a device already in use by other application)\n");
goto error;
}
+ ctx->is_running = 1;
ret = 0;
@@ -1932,6 +1973,7 @@ const AVInputFormat ff_dshow_demuxer = {
.read_packet = dshow_read_packet,
.read_close = dshow_read_close,
.get_device_list= dshow_get_device_list,
+ .control_message= dshow_control_message,
.flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK,
.priv_class = &dshow_class,
};
diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h
index b548cd7afc..d0dd35a670 100644
--- a/libavdevice/dshow_capture.h
+++ b/libavdevice/dshow_capture.h
@@ -331,6 +331,7 @@ struct dshow_ctx {
IMediaControl *control;
IMediaEvent *media_event;
+ int is_running;
enum AVPixelFormat pixel_format;
enum AVCodecID video_codec_id;
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 4efe7f8649..fb1dccb6b3 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
#define LIBAVDEVICE_VERSION_MINOR 7
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 04/21] avdevice: add control message requesting to show config dialog
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (2 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 03/21] avdevice/dshow: implement control_message interface Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 05/21] avdevice/dshow: accept show config dialog control message Diederick Niehorster
` (17 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
This control message can be used to programmatically ask a device to
show one of its configuration dialogs.
Adding documentation of this message's int argument.
Bumping avdevice version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
doc/indevs.texi | 34 ++++++++++++++++++++++++++++++++++
libavdevice/avdevice.h | 10 ++++++++++
libavdevice/version.h | 4 ++--
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 9d8020311a..0302859552 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -682,6 +682,40 @@ $ ffmpeg -f dshow -show_video_device_dialog true -crossbar_video_input_pin_numbe
@end itemize
+@subsection Libavdevice user notes
+
+The dshow device supports the @code{avdevice_app_to_dev_control_message}
+interface.
+
+It understands the @code{AV_APP_TO_DEV_PAUSE}, @code{AV_APP_TO_DEV_PLAY}
+and @code{AV_APP_TO_DEV_TOGGLE_PAUSE} commands, which respective stop and
+start whether data is captured from the connected device, and toggle
+capture state.
+
+It furthermore understands the @code{AV_APP_TO_DEV_CONFIG} message, which
+requests the device to show a configuration dialog (if available). An
+@code{int} should be passed along with this command to indicate which
+configuration dialog should be shown. The bits in this @code{int} have
+the following meaning:
+
+@itemize @bullet
+@item
+1st bit: If set, the dialog for the audio device will be shown. If not set
+the dialog for the video device will be shown.
+
+@item
+2nd bit: If set, show property dialog for the audio or video capture device,
+allowing to change audio or video filter properties and configurations
+manually.
+
+@item
+3rd bit: If set, show property dialog where crossbar pin routings of the
+audio/video device can be manually modified.
+
+@item
+4th bit: If set, show property dialog where TV channels and frequencies can be manually modified (in case of video device), or TV audio (like mono vs. stereo, Language A, B or C) can be manually modified in case of audio device.
+@end itemize
+
@section fbdev
Linux framebuffer input device.
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index db16a2f27e..74e9518a8e 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -206,6 +206,16 @@ enum AVAppToDevMessageType {
*/
AV_APP_TO_DEV_GET_VOLUME = MKBETAG('G', 'V', 'O', 'L'),
AV_APP_TO_DEV_GET_MUTE = MKBETAG('G', 'M', 'U', 'T'),
+
+ /**
+ * Request to show configuration dialog.
+ *
+ * If device has a configuration dialog of type indicated by
+ * data, show it.
+ *
+ * data: int (device-specific).
+ */
+ AV_APP_TO_DEV_CONFIG = MKBETAG('C', 'O', 'N', 'F'),
};
/**
diff --git a/libavdevice/version.h b/libavdevice/version.h
index fb1dccb6b3..f27f9ad9bf 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -30,8 +30,8 @@
#include "version_major.h"
-#define LIBAVDEVICE_VERSION_MINOR 7
-#define LIBAVDEVICE_VERSION_MICRO 101
+#define LIBAVDEVICE_VERSION_MINOR 8
+#define LIBAVDEVICE_VERSION_MICRO 100
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 05/21] avdevice/dshow: accept show config dialog control message
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (3 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 04/21] avdevice: add control message requesting to show config dialog Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 06/21] avdevice/dshow: add config dialog command for crossbar and tv tuner Diederick Niehorster
` (16 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
DirectShow source will pop up its configuration dialog when
AV_APP_TO_DEV_CONFIG is received. Implementation for several other
possible configuration dialogs is more involved and will be provided in
the next commit.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 652e093204..78194406b5 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -1508,6 +1508,7 @@ static int dshow_control_message(AVFormatContext *avctx, int type, void *data, s
struct dshow_ctx *ctx = avctx->priv_data;
int run_state = ctx->is_running;
HRESULT hr;
+ int ret = 0;
switch (type) {
case AV_APP_TO_DEV_PAUSE:
@@ -1519,6 +1520,32 @@ static int dshow_control_message(AVFormatContext *avctx, int type, void *data, s
case AV_APP_TO_DEV_TOGGLE_PAUSE:
run_state = !run_state;
break;
+ case AV_APP_TO_DEV_CONFIG: {
+ /* For documentation of dialog variable, see ffmpeg-devices.html in docs */
+ int dialog;
+ enum dshowDeviceType devtype;
+
+ if (!data)
+ av_log(avctx, AV_LOG_ERROR, "Use the data argument to indicate which dialog should be shown.");
+ dialog = *(int *) data;
+ devtype = (dialog & 1) ? AudioDevice : VideoDevice;
+
+ if (dialog & 1<<1) {
+ // device_dialog
+ if (ctx->device_filter[devtype])
+ ff_dshow_show_filter_properties(ctx->device_filter[devtype], avctx);
+ } else if (dialog & 1<<2) {
+ // crossbar_connection_dialog
+ // TODO
+ } else if (dialog & 1<<3) {
+ // tv_tuner_dialog
+ // TODO
+ }
+ break;
+ }
+
+ default:
+ ret = AVERROR(ENOSYS);
}
// if play state change requested, apply
@@ -1539,7 +1566,7 @@ static int dshow_control_message(AVFormatContext *avctx, int type, void *data, s
ctx->is_running = run_state;
}
- return 0;
+ return ret;
}
static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 06/21] avdevice/dshow: add config dialog command for crossbar and tv tuner
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (4 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 05/21] avdevice/dshow: accept show config dialog control message Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API" Diederick Niehorster
` (15 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
The "show config dialog" command message can now also trigger dialog
boxes for the crossbar connecting pins filter the analog tuner
audio / analog tuner filters.
Bumping avdevice version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 51 ++++++++++++++++++--
libavdevice/dshow_capture.h | 10 ++++
libavdevice/dshow_crossbar.c | 91 +++++++++++++++++++++++-------------
libavdevice/version.h | 2 +-
4 files changed, 115 insertions(+), 39 deletions(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 78194406b5..a780351170 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -240,6 +240,11 @@ dshow_read_close(AVFormatContext *s)
struct dshow_ctx *ctx = s->priv_data;
PacketListEntry *pktl;
+ if (ctx->graph_builder2[VideoDevice])
+ ICaptureGraphBuilder2_Release(ctx->graph_builder2[VideoDevice]);
+ if (ctx->graph_builder2[AudioDevice])
+ ICaptureGraphBuilder2_Release(ctx->graph_builder2[AudioDevice]);
+
if (ctx->control) {
IMediaControl_Stop(ctx->control);
IMediaControl_Release(ctx->control);
@@ -1464,6 +1469,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
av_log(avctx, AV_LOG_ERROR, "Could not create CaptureGraphBuilder2\n");
goto error;
}
+ ctx->graph_builder2[devtype] = graph_builder2;
ICaptureGraphBuilder2_SetFiltergraph(graph_builder2, graph);
if (r != S_OK) {
av_log(avctx, AV_LOG_ERROR, "Could not set graph for CaptureGraphBuilder2\n");
@@ -1488,9 +1494,6 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
ret = 0;
error:
- if (graph_builder2 != NULL)
- ICaptureGraphBuilder2_Release(graph_builder2);
-
if (pers_stream)
IPersistStream_Release(pers_stream);
@@ -1536,10 +1539,48 @@ static int dshow_control_message(AVFormatContext *avctx, int type, void *data, s
ff_dshow_show_filter_properties(ctx->device_filter[devtype], avctx);
} else if (dialog & 1<<2) {
// crossbar_connection_dialog
- // TODO
+ if (ctx->device_filter[devtype] && ctx->graph_builder2[devtype]) {
+ IAMCrossbar *cross_bar = NULL;
+ IBaseFilter *cross_bar_base_filter = NULL;
+ hr = ff_dshow_get_crossbar_and_filter(ctx->graph_builder2[devtype], ctx->device_filter[devtype], cross_bar, &cross_bar_base_filter);
+
+ if (hr == S_OK && cross_bar_base_filter)
+ ff_dshow_show_filter_properties(cross_bar_base_filter, avctx);
+
+ if (cross_bar)
+ IAMCrossbar_Release(cross_bar);
+ if (cross_bar_base_filter)
+ IBaseFilter_Release(cross_bar_base_filter);
+ }
} else if (dialog & 1<<3) {
// tv_tuner_dialog
- // TODO
+ if (ctx->device_filter[devtype] && ctx->graph_builder2[devtype]) {
+ if (devtype == VideoDevice) {
+ IAMTVTuner *tv_tuner_filter = NULL;
+ IBaseFilter *tv_tuner_base_filter = NULL;
+ hr = ff_dshow_get_tvtuner_and_filter(ctx->graph_builder2[devtype], ctx->device_filter[devtype], tv_tuner_filter, tv_tuner_base_filter);
+
+ if (hr == S_OK && tv_tuner_base_filter)
+ ff_dshow_show_filter_properties(tv_tuner_base_filter, avctx);
+
+ if (tv_tuner_filter)
+ IAMTVTuner_Release(tv_tuner_filter);
+ if (tv_tuner_base_filter)
+ IBaseFilter_Release(tv_tuner_base_filter);
+ } else {
+ IAMAudioInputMixer *tv_audio_filter = NULL;
+ IBaseFilter *tv_audio_base_filter = NULL;
+ hr = ff_dshow_get_audiomixer_and_filter(ctx->graph_builder2[devtype], ctx->device_filter[devtype], tv_audio_filter, tv_audio_base_filter);
+
+ if (hr == S_OK && tv_audio_base_filter)
+ ff_dshow_show_filter_properties(tv_audio_base_filter, avctx);
+
+ if (tv_audio_filter)
+ IAMAudioInputMixer_Release(tv_audio_filter);
+ if (tv_audio_base_filter)
+ IBaseFilter_Release(tv_audio_base_filter);
+ }
+ }
}
break;
}
diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h
index d0dd35a670..94ba9896b7 100644
--- a/libavdevice/dshow_capture.h
+++ b/libavdevice/dshow_capture.h
@@ -318,6 +318,7 @@ struct dshow_ctx {
IPin *device_pin[2];
DShowFilter *capture_filter[2];
DShowPin *capture_pin[2];
+ ICaptureGraphBuilder2 *graph_builder2[2];
HANDLE mutex;
HANDLE event[2]; /* event[0] is set by DirectShow
@@ -352,6 +353,15 @@ struct dshow_ctx {
HRESULT ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2,
IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx);
+HRESULT ff_dshow_get_crossbar_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter,
+ IAMCrossbar *cross_bar, IBaseFilter **cross_bar_base_filter);
+
+HRESULT ff_dshow_get_tvtuner_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter,
+ IAMTVTuner *tv_tuner_filter, IBaseFilter *tv_tuner_base_filter);
+
+HRESULT ff_dshow_get_audiomixer_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter,
+ IAMAudioInputMixer *tv_audio_filter, IBaseFilter *tv_audio_base_filter);
+
void ff_dshow_show_filter_properties(IBaseFilter *pFilter, AVFormatContext *avctx);
#endif /* AVDEVICE_DSHOW_CAPTURE_H */
diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c
index 961defe690..6b714e849c 100644
--- a/libavdevice/dshow_crossbar.c
+++ b/libavdevice/dshow_crossbar.c
@@ -133,6 +133,44 @@ setup_crossbar_options(IAMCrossbar *cross_bar, enum dshowDeviceType devtype, AVF
return S_OK;
}
+HRESULT
+ff_dshow_get_crossbar_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter,
+ IAMCrossbar *cross_bar, IBaseFilter **cross_bar_base_filter)
+{
+ HRESULT hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, (const GUID *) NULL,
+ device_filter, &IID_IAMCrossbar, (void **) &cross_bar);
+ if (hr != S_OK)
+ /* no crossbar found */
+ return hr;
+
+ if (cross_bar_base_filter)
+ hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void**)cross_bar_base_filter);
+
+ return hr;
+}
+
+HRESULT
+ff_dshow_get_tvtuner_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter,
+ IAMTVTuner *tv_tuner_filter, IBaseFilter *tv_tuner_base_filter)
+{
+ HRESULT hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL,
+ device_filter, &IID_IAMTVTuner, (void **) &tv_tuner_filter);
+ if (hr == S_OK)
+ hr = IAMCrossbar_QueryInterface(tv_tuner_filter, &IID_IBaseFilter, (void **) &tv_tuner_base_filter);
+ return hr;
+}
+
+HRESULT
+ff_dshow_get_audiomixer_and_filter(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter,
+ IAMAudioInputMixer *tv_audio_filter, IBaseFilter *tv_audio_base_filter)
+{
+ HRESULT hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL,
+ device_filter, &IID_IAMTVAudio, (void **) &tv_audio_filter);
+ if (hr == S_OK)
+ hr = IAMCrossbar_QueryInterface(tv_audio_filter, &IID_IBaseFilter, (void **) &tv_audio_base_filter);
+ return hr;
+}
+
/**
* Given a fully constructed graph, check if there is a cross bar filter, and configure its pins if so.
*/
@@ -140,55 +178,42 @@ HRESULT
ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2,
IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx)
{
- struct dshow_ctx *ctx = avctx->priv_data;
- IAMCrossbar *cross_bar = NULL;
- IBaseFilter *cross_bar_base_filter = NULL;
- IAMTVTuner *tv_tuner_filter = NULL;
- IBaseFilter *tv_tuner_base_filter = NULL;
- IAMAudioInputMixer *tv_audio_filter = NULL;
- IBaseFilter *tv_audio_base_filter = NULL;
+ struct dshow_ctx *ctx = avctx->priv_data;
+ IAMCrossbar *cross_bar = NULL;
+ IBaseFilter *cross_bar_base_filter = NULL;
+ IAMTVTuner *tv_tuner_filter = NULL;
+ IBaseFilter *tv_tuner_base_filter = NULL;
+ IAMAudioInputMixer *tv_audio_filter = NULL;
+ IBaseFilter *tv_audio_base_filter = NULL;
HRESULT hr;
+ int should_show_crossbar_properties = (devtype == VideoDevice) ? ctx->show_video_crossbar_connection_dialog : ctx->show_audio_crossbar_connection_dialog;
- hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, (const GUID *) NULL,
- device_filter, &IID_IAMCrossbar, (void**) &cross_bar);
+ hr = ff_dshow_get_crossbar_and_filter(graph_builder2, device_filter, cross_bar, should_show_crossbar_properties ? &cross_bar_base_filter : NULL);
if (hr != S_OK) {
- /* no crossbar found */
- hr = S_OK;
+ if (!cross_bar)
+ /* no crossbar found */
+ hr = S_OK;
goto end;
}
+
/* TODO some TV tuners apparently have multiple crossbars? */
- if (devtype == VideoDevice && ctx->show_video_crossbar_connection_dialog ||
- devtype == AudioDevice && ctx->show_audio_crossbar_connection_dialog) {
- hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void **) &cross_bar_base_filter);
- if (hr != S_OK)
- goto end;
+ if (should_show_crossbar_properties && cross_bar_base_filter)
ff_dshow_show_filter_properties(cross_bar_base_filter, avctx);
- }
if (devtype == VideoDevice && ctx->show_analog_tv_tuner_dialog) {
- hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL,
- device_filter, &IID_IAMTVTuner, (void**) &tv_tuner_filter);
- if (hr == S_OK) {
- hr = IAMCrossbar_QueryInterface(tv_tuner_filter, &IID_IBaseFilter, (void **) &tv_tuner_base_filter);
- if (hr != S_OK)
- goto end;
+ hr = ff_dshow_get_tvtuner_and_filter(graph_builder2, device_filter, tv_tuner_filter, tv_tuner_base_filter);
+ if (hr == S_OK && tv_tuner_base_filter)
ff_dshow_show_filter_properties(tv_tuner_base_filter, avctx);
- } else {
+ else
av_log(avctx, AV_LOG_WARNING, "unable to find a tv tuner to display dialog for!");
- }
}
if (devtype == AudioDevice && ctx->show_analog_tv_tuner_audio_dialog) {
- hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL,
- device_filter, &IID_IAMTVAudio, (void**) &tv_audio_filter);
- if (hr == S_OK) {
- hr = IAMCrossbar_QueryInterface(tv_audio_filter, &IID_IBaseFilter, (void **) &tv_audio_base_filter);
- if (hr != S_OK)
- goto end;
+ hr = ff_dshow_get_audiomixer_and_filter(graph_builder2, device_filter, tv_audio_filter, tv_audio_base_filter);
+ if (hr == S_OK && tv_audio_base_filter)
ff_dshow_show_filter_properties(tv_audio_base_filter, avctx);
- } else {
+ else
av_log(avctx, AV_LOG_WARNING, "unable to find a tv audio tuner to display dialog for!");
- }
}
hr = setup_crossbar_options(cross_bar, devtype, avctx);
diff --git a/libavdevice/version.h b/libavdevice/version.h
index f27f9ad9bf..e2c8757b27 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
#define LIBAVDEVICE_VERSION_MINOR 8
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API"
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (5 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 06/21] avdevice/dshow: add config dialog command for crossbar and tv tuner Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-05-10 17:24 ` Andreas Rheinhardt
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 08/21] avdevice/avdevice: clean up avdevice_capabilities_create Diederick Niehorster
` (14 subsequent siblings)
21 siblings, 1 reply; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
This reverts commit 4f49ca7bbc75a9db4cdf93f27f95a668c751f160. The next
few patches clean up the API and implement this capability for
avdevice/dshow.
Bumping avformat and avdevice version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 71 ++++++++++++++++++++++++++++++++++++++----
libavdevice/avdevice.h | 5 ---
libavdevice/version.h | 4 +--
libavformat/avformat.h | 21 +++++++++++++
libavformat/version.h | 2 +-
5 files changed, 89 insertions(+), 14 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 43d3406670..d367189532 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -28,11 +28,39 @@
#include "libavutil/ffversion.h"
const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
-#if FF_API_DEVICE_CAPABILITIES
+#define E AV_OPT_FLAG_ENCODING_PARAM
+#define D AV_OPT_FLAG_DECODING_PARAM
+#define A AV_OPT_FLAG_AUDIO_PARAM
+#define V AV_OPT_FLAG_VIDEO_PARAM
+#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x)
+
const AVOption av_device_capabilities[] = {
+ { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT,
+ {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V },
+ { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT,
+ {.i64 = AV_SAMPLE_FMT_NONE}, AV_SAMPLE_FMT_NONE, INT_MAX, E|D|A },
+ { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT,
+ {.i64 = -1}, -1, INT_MAX, E|D|A },
+ { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT,
+ {.i64 = -1}, -1, INT_MAX, E|D|A },
+ { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
+ {.i64 = -1}, -1, INT_MAX, E|D|A },
+ { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT,
+ {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, INT_MAX, E|D|V },
+ { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE,
+ {.str = NULL}, -1, INT_MAX, E|D|V },
+ { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE,
+ {.str = NULL}, -1, INT_MAX, E|D|V },
+ { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL,
+ {.dbl = -1}, -1, INT_MAX, E|D|V },
{ NULL }
};
-#endif
+
+#undef E
+#undef D
+#undef A
+#undef V
+#undef OFFSET
unsigned avdevice_version(void)
{
@@ -81,18 +109,49 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToA
return s->control_message_cb(s, type, data, data_size);
}
-#if FF_API_DEVICE_CAPABILITIES
int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
AVDictionary **device_options)
{
- return AVERROR(ENOSYS);
+ int ret;
+ av_assert0(s && caps);
+ av_assert0(s->iformat || s->oformat);
+ if ((s->oformat && !s->oformat->create_device_capabilities) ||
+ (s->iformat && !s->iformat->create_device_capabilities))
+ return AVERROR(ENOSYS);
+ *caps = av_mallocz(sizeof(**caps));
+ if (!(*caps))
+ return AVERROR(ENOMEM);
+ (*caps)->device_context = s;
+ if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0))
+ goto fail;
+ if (s->iformat) {
+ if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0)
+ goto fail;
+ } else {
+ if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0)
+ goto fail;
+ }
+ av_opt_set_defaults(*caps);
+ return 0;
+ fail:
+ av_freep(caps);
+ return ret;
}
void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s)
{
- return;
+ if (!s || !caps || !(*caps))
+ return;
+ av_assert0(s->iformat || s->oformat);
+ if (s->iformat) {
+ if (s->iformat->free_device_capabilities)
+ s->iformat->free_device_capabilities(s, *caps);
+ } else {
+ if (s->oformat->free_device_capabilities)
+ s->oformat->free_device_capabilities(s, *caps);
+ }
+ av_freep(caps);
}
-#endif
int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list)
{
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index 74e9518a8e..9724e7edf5 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -347,7 +347,6 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
enum AVDevToAppMessageType type,
void *data, size_t data_size);
-#if FF_API_DEVICE_CAPABILITIES
/**
* Following API allows user to probe device capabilities (supported codecs,
* pixel formats, sample formats, resolutions, channel counts, etc).
@@ -443,7 +442,6 @@ typedef struct AVDeviceCapabilitiesQuery {
/**
* AVOption table used by devices to implement device capabilities API. Should not be used by a user.
*/
-attribute_deprecated
extern const AVOption av_device_capabilities[];
/**
@@ -463,7 +461,6 @@ extern const AVOption av_device_capabilities[];
*
* @return >= 0 on success, negative otherwise.
*/
-attribute_deprecated
int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
AVDictionary **device_options);
@@ -473,9 +470,7 @@ int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatConte
* @param caps Device capabilities data to be freed.
* @param s Context of the device.
*/
-attribute_deprecated
void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
-#endif
/**
* Structure describes basic parameters of the device.
diff --git a/libavdevice/version.h b/libavdevice/version.h
index e2c8757b27..7c132f2174 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -30,8 +30,8 @@
#include "version_major.h"
-#define LIBAVDEVICE_VERSION_MINOR 8
-#define LIBAVDEVICE_VERSION_MICRO 101
+#define LIBAVDEVICE_VERSION_MINOR 9
+#define LIBAVDEVICE_VERSION_MICRO 100
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 06db024559..027a914e13 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -617,6 +617,16 @@ typedef struct AVOutputFormat {
* @see avdevice_list_devices() for more details.
*/
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
+ /**
+ * Initialize device capabilities submodule.
+ * @see avdevice_capabilities_create() for more details.
+ */
+ int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
+ /**
+ * Free device capabilities submodule.
+ * @see avdevice_capabilities_free() for more details.
+ */
+ int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
enum AVCodecID data_codec; /**< default data codec */
/**
* Initialize format. May allocate data here, and set any AVFormatContext or
@@ -797,6 +807,17 @@ typedef struct AVInputFormat {
*/
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
+ /**
+ * Initialize device capabilities submodule.
+ * @see avdevice_capabilities_create() for more details.
+ */
+ int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
+
+ /**
+ * Free device capabilities submodule.
+ * @see avdevice_capabilities_free() for more details.
+ */
+ int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
} AVInputFormat;
/**
* @}
diff --git a/libavformat/version.h b/libavformat/version.h
index d195704a31..88d6f750a2 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
#include "version_major.h"
-#define LIBAVFORMAT_VERSION_MINOR 22
+#define LIBAVFORMAT_VERSION_MINOR 23
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API"
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API" Diederick Niehorster
@ 2022-05-10 17:24 ` Andreas Rheinhardt
2022-05-10 17:40 ` Hendrik Leppkes
2022-05-12 8:17 ` Diederick C. Niehorster
0 siblings, 2 replies; 26+ messages in thread
From: Andreas Rheinhardt @ 2022-05-10 17:24 UTC (permalink / raw)
To: ffmpeg-devel
Diederick Niehorster:
> This reverts commit 4f49ca7bbc75a9db4cdf93f27f95a668c751f160. The next
> few patches clean up the API and implement this capability for
> avdevice/dshow.
>
> Bumping avformat and avdevice version.
>
> Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
> ---
> libavdevice/avdevice.c | 71 ++++++++++++++++++++++++++++++++++++++----
> libavdevice/avdevice.h | 5 ---
> libavdevice/version.h | 4 +--
> libavformat/avformat.h | 21 +++++++++++++
> libavformat/version.h | 2 +-
> 5 files changed, 89 insertions(+), 14 deletions(-)
>
> diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
> index 43d3406670..d367189532 100644
> --- a/libavdevice/avdevice.c
> +++ b/libavdevice/avdevice.c
> @@ -28,11 +28,39 @@
> #include "libavutil/ffversion.h"
> const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
>
> -#if FF_API_DEVICE_CAPABILITIES
> +#define E AV_OPT_FLAG_ENCODING_PARAM
> +#define D AV_OPT_FLAG_DECODING_PARAM
> +#define A AV_OPT_FLAG_AUDIO_PARAM
> +#define V AV_OPT_FLAG_VIDEO_PARAM
> +#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x)
> +
> const AVOption av_device_capabilities[] = {
> + { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT,
> + {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V },
> + { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT,
> + {.i64 = AV_SAMPLE_FMT_NONE}, AV_SAMPLE_FMT_NONE, INT_MAX, E|D|A },
> + { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT,
> + {.i64 = -1}, -1, INT_MAX, E|D|A },
> + { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT,
> + {.i64 = -1}, -1, INT_MAX, E|D|A },
> + { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
> + {.i64 = -1}, -1, INT_MAX, E|D|A },
> + { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT,
> + {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, INT_MAX, E|D|V },
> + { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE,
> + {.str = NULL}, -1, INT_MAX, E|D|V },
> + { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE,
> + {.str = NULL}, -1, INT_MAX, E|D|V },
> + { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL,
> + {.dbl = -1}, -1, INT_MAX, E|D|V },
> { NULL }
> };
> -#endif
> +
> +#undef E
> +#undef D
> +#undef A
> +#undef V
> +#undef OFFSET
>
> unsigned avdevice_version(void)
> {
> @@ -81,18 +109,49 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToA
> return s->control_message_cb(s, type, data, data_size);
> }
>
> -#if FF_API_DEVICE_CAPABILITIES
> int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
> AVDictionary **device_options)
> {
> - return AVERROR(ENOSYS);
> + int ret;
> + av_assert0(s && caps);
> + av_assert0(s->iformat || s->oformat);
> + if ((s->oformat && !s->oformat->create_device_capabilities) ||
> + (s->iformat && !s->iformat->create_device_capabilities))
> + return AVERROR(ENOSYS);
> + *caps = av_mallocz(sizeof(**caps));
> + if (!(*caps))
> + return AVERROR(ENOMEM);
> + (*caps)->device_context = s;
> + if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0))
> + goto fail;
> + if (s->iformat) {
> + if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0)
> + goto fail;
> + } else {
> + if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0)
> + goto fail;
> + }
> + av_opt_set_defaults(*caps);
> + return 0;
> + fail:
> + av_freep(caps);
> + return ret;
> }
>
> void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s)
> {
> - return;
> + if (!s || !caps || !(*caps))
> + return;
> + av_assert0(s->iformat || s->oformat);
> + if (s->iformat) {
> + if (s->iformat->free_device_capabilities)
> + s->iformat->free_device_capabilities(s, *caps);
> + } else {
> + if (s->oformat->free_device_capabilities)
> + s->oformat->free_device_capabilities(s, *caps);
> + }
> + av_freep(caps);
> }
> -#endif
>
> int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list)
> {
> diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
> index 74e9518a8e..9724e7edf5 100644
> --- a/libavdevice/avdevice.h
> +++ b/libavdevice/avdevice.h
> @@ -347,7 +347,6 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
> enum AVDevToAppMessageType type,
> void *data, size_t data_size);
>
> -#if FF_API_DEVICE_CAPABILITIES
> /**
> * Following API allows user to probe device capabilities (supported codecs,
> * pixel formats, sample formats, resolutions, channel counts, etc).
> @@ -443,7 +442,6 @@ typedef struct AVDeviceCapabilitiesQuery {
> /**
> * AVOption table used by devices to implement device capabilities API. Should not be used by a user.
> */
> -attribute_deprecated
> extern const AVOption av_device_capabilities[];
>
> /**
> @@ -463,7 +461,6 @@ extern const AVOption av_device_capabilities[];
> *
> * @return >= 0 on success, negative otherwise.
> */
> -attribute_deprecated
> int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
> AVDictionary **device_options);
>
> @@ -473,9 +470,7 @@ int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatConte
> * @param caps Device capabilities data to be freed.
> * @param s Context of the device.
> */
> -attribute_deprecated
> void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
> -#endif
>
> /**
> * Structure describes basic parameters of the device.
> diff --git a/libavdevice/version.h b/libavdevice/version.h
> index e2c8757b27..7c132f2174 100644
> --- a/libavdevice/version.h
> +++ b/libavdevice/version.h
> @@ -30,8 +30,8 @@
>
> #include "version_major.h"
>
> -#define LIBAVDEVICE_VERSION_MINOR 8
> -#define LIBAVDEVICE_VERSION_MICRO 101
> +#define LIBAVDEVICE_VERSION_MINOR 9
> +#define LIBAVDEVICE_VERSION_MICRO 100
>
> #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
> LIBAVDEVICE_VERSION_MINOR, \
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 06db024559..027a914e13 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -617,6 +617,16 @@ typedef struct AVOutputFormat {
> * @see avdevice_list_devices() for more details.
> */
> int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
> + /**
> + * Initialize device capabilities submodule.
> + * @see avdevice_capabilities_create() for more details.
> + */
> + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> + /**
> + * Free device capabilities submodule.
> + * @see avdevice_capabilities_free() for more details.
> + */
> + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> enum AVCodecID data_codec; /**< default data codec */
> /**
> * Initialize format. May allocate data here, and set any AVFormatContext or
> @@ -797,6 +807,17 @@ typedef struct AVInputFormat {
> */
> int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
>
> + /**
> + * Initialize device capabilities submodule.
> + * @see avdevice_capabilities_create() for more details.
> + */
> + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> +
> + /**
> + * Free device capabilities submodule.
> + * @see avdevice_capabilities_free() for more details.
> + */
> + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> } AVInputFormat;
> /**
> * @}
> diff --git a/libavformat/version.h b/libavformat/version.h
> index d195704a31..88d6f750a2 100644
> --- a/libavformat/version.h
> +++ b/libavformat/version.h
> @@ -32,7 +32,7 @@
>
> #include "version_major.h"
>
> -#define LIBAVFORMAT_VERSION_MINOR 22
> +#define LIBAVFORMAT_VERSION_MINOR 23
> #define LIBAVFORMAT_VERSION_MICRO 100
>
> #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
I have not really looked at the actual content of your dshow patches (as
I know nothing about dshow). But I really don't like the thought that
something is added to AVInput/OutputFormat that only a tiny fraction of
all (de)muxers will likely ever use. I think it would be more efficient
to add a single callback for the seldomly used types of callback like this:
int (*generic_callback)(struct AVFormatContext *s, int type, void
*priv1, void *priv2, int64_t num)
The uses of priv1, priv2 (and whether they are used at all) would depend
upon the type; they can be pointers to structures (which structures
depends upon type) to allow passing more arguments than otherwise
possible by the signature of generic_callback. type should actually be
an enum, but one can't forward declare an enum, so as long as the
internals are in public headers it won't be an enum.
The typical implementation of such a callback would be with a switch:
static int generic_callback(AVFormatContext *s, int type, void *priv1,
void *priv2, int64_t num)
{
switch (type) {
case FOO:
return handle_foo(s, priv1, priv2, num);
case BAR:
return handle_bar(s, priv1, priv2, num);
default:
return AVERROR(ENOSYS);
}
The typical calling code would look like this:
{
if (!s->oformat->generic_callback)
AVERROR(ENOSYS);
/* In case this type needs so many arguments that
* a structure for them is used they should be prepared here. */
ret = s->oformat->generic_callback(s, type_foo, /* other arguments);
/* Inspect ret or just return it; notice that ret may very well be
AVERROR(ENOSYS) again, because the existence of the generic callback
does not imply that every type is supported. */
}
There are more callbacks that should be moved into this generic callback
besides the callbacks that you intend to add: The read_play and
read_pause callbacks which are only supported by a single demuxer. E.g.
av_read_play would look like this:
int av_read_play(AVFormatContext *s)
{
if (s->iformat->generic_callback) {
int ret = s->iformat->generic_callback(s, FF_CB_TYPE_READ_PLAY,
NULL, NULL, 0);
if (ret != AVERROR(ENOSYS))
return ret;
}
if (s->pb)
return avio_pause(s->pb, 0);
return AVERROR(ENOSYS);
}
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API"
2022-05-10 17:24 ` Andreas Rheinhardt
@ 2022-05-10 17:40 ` Hendrik Leppkes
2022-05-12 8:17 ` Diederick C. Niehorster
1 sibling, 0 replies; 26+ messages in thread
From: Hendrik Leppkes @ 2022-05-10 17:40 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, May 10, 2022 at 7:25 PM Andreas Rheinhardt
<andreas.rheinhardt@outlook.com> wrote:
>
> Diederick Niehorster:
> > This reverts commit 4f49ca7bbc75a9db4cdf93f27f95a668c751f160. The next
> > few patches clean up the API and implement this capability for
> > avdevice/dshow.
> >
> > Bumping avformat and avdevice version.
> >
> > Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
> > ---
> > libavdevice/avdevice.c | 71 ++++++++++++++++++++++++++++++++++++++----
> > libavdevice/avdevice.h | 5 ---
> > libavdevice/version.h | 4 +--
> > libavformat/avformat.h | 21 +++++++++++++
> > libavformat/version.h | 2 +-
> > 5 files changed, 89 insertions(+), 14 deletions(-)
> >
> > diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
> > index 43d3406670..d367189532 100644
> > --- a/libavdevice/avdevice.c
> > +++ b/libavdevice/avdevice.c
> > @@ -28,11 +28,39 @@
> > #include "libavutil/ffversion.h"
> > const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
> >
> > -#if FF_API_DEVICE_CAPABILITIES
> > +#define E AV_OPT_FLAG_ENCODING_PARAM
> > +#define D AV_OPT_FLAG_DECODING_PARAM
> > +#define A AV_OPT_FLAG_AUDIO_PARAM
> > +#define V AV_OPT_FLAG_VIDEO_PARAM
> > +#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x)
> > +
> > const AVOption av_device_capabilities[] = {
> > + { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT,
> > + {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V },
> > + { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT,
> > + {.i64 = AV_SAMPLE_FMT_NONE}, AV_SAMPLE_FMT_NONE, INT_MAX, E|D|A },
> > + { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT,
> > + {.i64 = -1}, -1, INT_MAX, E|D|A },
> > + { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT,
> > + {.i64 = -1}, -1, INT_MAX, E|D|A },
> > + { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
> > + {.i64 = -1}, -1, INT_MAX, E|D|A },
> > + { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT,
> > + {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, INT_MAX, E|D|V },
> > + { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE,
> > + {.str = NULL}, -1, INT_MAX, E|D|V },
> > + { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE,
> > + {.str = NULL}, -1, INT_MAX, E|D|V },
> > + { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL,
> > + {.dbl = -1}, -1, INT_MAX, E|D|V },
> > { NULL }
> > };
> > -#endif
> > +
> > +#undef E
> > +#undef D
> > +#undef A
> > +#undef V
> > +#undef OFFSET
> >
> > unsigned avdevice_version(void)
> > {
> > @@ -81,18 +109,49 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToA
> > return s->control_message_cb(s, type, data, data_size);
> > }
> >
> > -#if FF_API_DEVICE_CAPABILITIES
> > int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
> > AVDictionary **device_options)
> > {
> > - return AVERROR(ENOSYS);
> > + int ret;
> > + av_assert0(s && caps);
> > + av_assert0(s->iformat || s->oformat);
> > + if ((s->oformat && !s->oformat->create_device_capabilities) ||
> > + (s->iformat && !s->iformat->create_device_capabilities))
> > + return AVERROR(ENOSYS);
> > + *caps = av_mallocz(sizeof(**caps));
> > + if (!(*caps))
> > + return AVERROR(ENOMEM);
> > + (*caps)->device_context = s;
> > + if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0))
> > + goto fail;
> > + if (s->iformat) {
> > + if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0)
> > + goto fail;
> > + } else {
> > + if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0)
> > + goto fail;
> > + }
> > + av_opt_set_defaults(*caps);
> > + return 0;
> > + fail:
> > + av_freep(caps);
> > + return ret;
> > }
> >
> > void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s)
> > {
> > - return;
> > + if (!s || !caps || !(*caps))
> > + return;
> > + av_assert0(s->iformat || s->oformat);
> > + if (s->iformat) {
> > + if (s->iformat->free_device_capabilities)
> > + s->iformat->free_device_capabilities(s, *caps);
> > + } else {
> > + if (s->oformat->free_device_capabilities)
> > + s->oformat->free_device_capabilities(s, *caps);
> > + }
> > + av_freep(caps);
> > }
> > -#endif
> >
> > int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list)
> > {
> > diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
> > index 74e9518a8e..9724e7edf5 100644
> > --- a/libavdevice/avdevice.h
> > +++ b/libavdevice/avdevice.h
> > @@ -347,7 +347,6 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
> > enum AVDevToAppMessageType type,
> > void *data, size_t data_size);
> >
> > -#if FF_API_DEVICE_CAPABILITIES
> > /**
> > * Following API allows user to probe device capabilities (supported codecs,
> > * pixel formats, sample formats, resolutions, channel counts, etc).
> > @@ -443,7 +442,6 @@ typedef struct AVDeviceCapabilitiesQuery {
> > /**
> > * AVOption table used by devices to implement device capabilities API. Should not be used by a user.
> > */
> > -attribute_deprecated
> > extern const AVOption av_device_capabilities[];
> >
> > /**
> > @@ -463,7 +461,6 @@ extern const AVOption av_device_capabilities[];
> > *
> > * @return >= 0 on success, negative otherwise.
> > */
> > -attribute_deprecated
> > int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
> > AVDictionary **device_options);
> >
> > @@ -473,9 +470,7 @@ int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatConte
> > * @param caps Device capabilities data to be freed.
> > * @param s Context of the device.
> > */
> > -attribute_deprecated
> > void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
> > -#endif
> >
> > /**
> > * Structure describes basic parameters of the device.
> > diff --git a/libavdevice/version.h b/libavdevice/version.h
> > index e2c8757b27..7c132f2174 100644
> > --- a/libavdevice/version.h
> > +++ b/libavdevice/version.h
> > @@ -30,8 +30,8 @@
> >
> > #include "version_major.h"
> >
> > -#define LIBAVDEVICE_VERSION_MINOR 8
> > -#define LIBAVDEVICE_VERSION_MICRO 101
> > +#define LIBAVDEVICE_VERSION_MINOR 9
> > +#define LIBAVDEVICE_VERSION_MICRO 100
> >
> > #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
> > LIBAVDEVICE_VERSION_MINOR, \
> > diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> > index 06db024559..027a914e13 100644
> > --- a/libavformat/avformat.h
> > +++ b/libavformat/avformat.h
> > @@ -617,6 +617,16 @@ typedef struct AVOutputFormat {
> > * @see avdevice_list_devices() for more details.
> > */
> > int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
> > + /**
> > + * Initialize device capabilities submodule.
> > + * @see avdevice_capabilities_create() for more details.
> > + */
> > + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > + /**
> > + * Free device capabilities submodule.
> > + * @see avdevice_capabilities_free() for more details.
> > + */
> > + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > enum AVCodecID data_codec; /**< default data codec */
> > /**
> > * Initialize format. May allocate data here, and set any AVFormatContext or
> > @@ -797,6 +807,17 @@ typedef struct AVInputFormat {
> > */
> > int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
> >
> > + /**
> > + * Initialize device capabilities submodule.
> > + * @see avdevice_capabilities_create() for more details.
> > + */
> > + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > +
> > + /**
> > + * Free device capabilities submodule.
> > + * @see avdevice_capabilities_free() for more details.
> > + */
> > + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > } AVInputFormat;
> > /**
> > * @}
> > diff --git a/libavformat/version.h b/libavformat/version.h
> > index d195704a31..88d6f750a2 100644
> > --- a/libavformat/version.h
> > +++ b/libavformat/version.h
> > @@ -32,7 +32,7 @@
> >
> > #include "version_major.h"
> >
> > -#define LIBAVFORMAT_VERSION_MINOR 22
> > +#define LIBAVFORMAT_VERSION_MINOR 23
> > #define LIBAVFORMAT_VERSION_MICRO 100
> >
> > #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
>
> I have not really looked at the actual content of your dshow patches (as
> I know nothing about dshow). But I really don't like the thought that
> something is added to AVInput/OutputFormat that only a tiny fraction of
> all (de)muxers will likely ever use. I think it would be more efficient
> to add a single callback for the seldomly used types of callback like this:
>
> int (*generic_callback)(struct AVFormatContext *s, int type, void
> *priv1, void *priv2, int64_t num)
>
Frankly, this is a terrible API design in the abstract name of
"efficiency". If something is very specific for devices, maybe your
efficiency goal should be to divorce them from AVInputFormat.
Just my 2c.
- Hendrik
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API"
2022-05-10 17:24 ` Andreas Rheinhardt
2022-05-10 17:40 ` Hendrik Leppkes
@ 2022-05-12 8:17 ` Diederick C. Niehorster
1 sibling, 0 replies; 26+ messages in thread
From: Diederick C. Niehorster @ 2022-05-12 8:17 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, May 10, 2022 at 7:25 PM Andreas Rheinhardt
<andreas.rheinhardt@outlook.com> wrote:
>
> Diederick Niehorster:
> > This reverts commit 4f49ca7bbc75a9db4cdf93f27f95a668c751f160. The next
> > few patches clean up the API and implement this capability for
> > avdevice/dshow.
> >
> > Bumping avformat and avdevice version.
> >
> > Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
> > ---
> > libavdevice/avdevice.c | 71 ++++++++++++++++++++++++++++++++++++++----
> > libavdevice/avdevice.h | 5 ---
> > libavdevice/version.h | 4 +--
> > libavformat/avformat.h | 21 +++++++++++++
> > libavformat/version.h | 2 +-
> > 5 files changed, 89 insertions(+), 14 deletions(-)
> >
> > diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
> > index 43d3406670..d367189532 100644
> > --- a/libavdevice/avdevice.c
> > +++ b/libavdevice/avdevice.c
> > @@ -28,11 +28,39 @@
> > #include "libavutil/ffversion.h"
> > const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
> >
> > -#if FF_API_DEVICE_CAPABILITIES
> > +#define E AV_OPT_FLAG_ENCODING_PARAM
> > +#define D AV_OPT_FLAG_DECODING_PARAM
> > +#define A AV_OPT_FLAG_AUDIO_PARAM
> > +#define V AV_OPT_FLAG_VIDEO_PARAM
> > +#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x)
> > +
> > const AVOption av_device_capabilities[] = {
> > + { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT,
> > + {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V },
> > + { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT,
> > + {.i64 = AV_SAMPLE_FMT_NONE}, AV_SAMPLE_FMT_NONE, INT_MAX, E|D|A },
> > + { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT,
> > + {.i64 = -1}, -1, INT_MAX, E|D|A },
> > + { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT,
> > + {.i64 = -1}, -1, INT_MAX, E|D|A },
> > + { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
> > + {.i64 = -1}, -1, INT_MAX, E|D|A },
> > + { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT,
> > + {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, INT_MAX, E|D|V },
> > + { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE,
> > + {.str = NULL}, -1, INT_MAX, E|D|V },
> > + { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE,
> > + {.str = NULL}, -1, INT_MAX, E|D|V },
> > + { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL,
> > + {.dbl = -1}, -1, INT_MAX, E|D|V },
> > { NULL }
> > };
> > -#endif
> > +
> > +#undef E
> > +#undef D
> > +#undef A
> > +#undef V
> > +#undef OFFSET
> >
> > unsigned avdevice_version(void)
> > {
> > @@ -81,18 +109,49 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToA
> > return s->control_message_cb(s, type, data, data_size);
> > }
> >
> > -#if FF_API_DEVICE_CAPABILITIES
> > int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
> > AVDictionary **device_options)
> > {
> > - return AVERROR(ENOSYS);
> > + int ret;
> > + av_assert0(s && caps);
> > + av_assert0(s->iformat || s->oformat);
> > + if ((s->oformat && !s->oformat->create_device_capabilities) ||
> > + (s->iformat && !s->iformat->create_device_capabilities))
> > + return AVERROR(ENOSYS);
> > + *caps = av_mallocz(sizeof(**caps));
> > + if (!(*caps))
> > + return AVERROR(ENOMEM);
> > + (*caps)->device_context = s;
> > + if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0))
> > + goto fail;
> > + if (s->iformat) {
> > + if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0)
> > + goto fail;
> > + } else {
> > + if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0)
> > + goto fail;
> > + }
> > + av_opt_set_defaults(*caps);
> > + return 0;
> > + fail:
> > + av_freep(caps);
> > + return ret;
> > }
> >
> > void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s)
> > {
> > - return;
> > + if (!s || !caps || !(*caps))
> > + return;
> > + av_assert0(s->iformat || s->oformat);
> > + if (s->iformat) {
> > + if (s->iformat->free_device_capabilities)
> > + s->iformat->free_device_capabilities(s, *caps);
> > + } else {
> > + if (s->oformat->free_device_capabilities)
> > + s->oformat->free_device_capabilities(s, *caps);
> > + }
> > + av_freep(caps);
> > }
> > -#endif
> >
> > int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list)
> > {
> > diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
> > index 74e9518a8e..9724e7edf5 100644
> > --- a/libavdevice/avdevice.h
> > +++ b/libavdevice/avdevice.h
> > @@ -347,7 +347,6 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
> > enum AVDevToAppMessageType type,
> > void *data, size_t data_size);
> >
> > -#if FF_API_DEVICE_CAPABILITIES
> > /**
> > * Following API allows user to probe device capabilities (supported codecs,
> > * pixel formats, sample formats, resolutions, channel counts, etc).
> > @@ -443,7 +442,6 @@ typedef struct AVDeviceCapabilitiesQuery {
> > /**
> > * AVOption table used by devices to implement device capabilities API. Should not be used by a user.
> > */
> > -attribute_deprecated
> > extern const AVOption av_device_capabilities[];
> >
> > /**
> > @@ -463,7 +461,6 @@ extern const AVOption av_device_capabilities[];
> > *
> > * @return >= 0 on success, negative otherwise.
> > */
> > -attribute_deprecated
> > int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
> > AVDictionary **device_options);
> >
> > @@ -473,9 +470,7 @@ int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatConte
> > * @param caps Device capabilities data to be freed.
> > * @param s Context of the device.
> > */
> > -attribute_deprecated
> > void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
> > -#endif
> >
> > /**
> > * Structure describes basic parameters of the device.
> > diff --git a/libavdevice/version.h b/libavdevice/version.h
> > index e2c8757b27..7c132f2174 100644
> > --- a/libavdevice/version.h
> > +++ b/libavdevice/version.h
> > @@ -30,8 +30,8 @@
> >
> > #include "version_major.h"
> >
> > -#define LIBAVDEVICE_VERSION_MINOR 8
> > -#define LIBAVDEVICE_VERSION_MICRO 101
> > +#define LIBAVDEVICE_VERSION_MINOR 9
> > +#define LIBAVDEVICE_VERSION_MICRO 100
> >
> > #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
> > LIBAVDEVICE_VERSION_MINOR, \
> > diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> > index 06db024559..027a914e13 100644
> > --- a/libavformat/avformat.h
> > +++ b/libavformat/avformat.h
> > @@ -617,6 +617,16 @@ typedef struct AVOutputFormat {
> > * @see avdevice_list_devices() for more details.
> > */
> > int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
> > + /**
> > + * Initialize device capabilities submodule.
> > + * @see avdevice_capabilities_create() for more details.
> > + */
> > + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > + /**
> > + * Free device capabilities submodule.
> > + * @see avdevice_capabilities_free() for more details.
> > + */
> > + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > enum AVCodecID data_codec; /**< default data codec */
> > /**
> > * Initialize format. May allocate data here, and set any AVFormatContext or
> > @@ -797,6 +807,17 @@ typedef struct AVInputFormat {
> > */
> > int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
> >
> > + /**
> > + * Initialize device capabilities submodule.
> > + * @see avdevice_capabilities_create() for more details.
> > + */
> > + int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > +
> > + /**
> > + * Free device capabilities submodule.
> > + * @see avdevice_capabilities_free() for more details.
> > + */
> > + int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
> > } AVInputFormat;
> > /**
> > * @}
> > diff --git a/libavformat/version.h b/libavformat/version.h
> > index d195704a31..88d6f750a2 100644
> > --- a/libavformat/version.h
> > +++ b/libavformat/version.h
> > @@ -32,7 +32,7 @@
> >
> > #include "version_major.h"
> >
> > -#define LIBAVFORMAT_VERSION_MINOR 22
> > +#define LIBAVFORMAT_VERSION_MINOR 23
> > #define LIBAVFORMAT_VERSION_MICRO 100
> >
> > #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
>
> I have not really looked at the actual content of your dshow patches (as
> I know nothing about dshow). But I really don't like the thought that
> something is added to AVInput/OutputFormat that only a tiny fraction of
> all (de)muxers will likely ever use.
No worries, its this higher level discussion we should have first.
> I think it would be more efficient
> to add a single callback for the seldomly used types of callback like this:
I don't think we should introduce a kind of second-class citizens who
are not to be seen and harder to interact with. Either implement a
functionality properly without extra unnecessary indirection, or
decide its not worth it.
> int (*generic_callback)(struct AVFormatContext *s, int type, void
> *priv1, void *priv2, int64_t num)
>
> The uses of priv1, priv2 (and whether they are used at all) would depend
> upon the type; they can be pointers to structures (which structures
> depends upon type) to allow passing more arguments than otherwise
> possible by the signature of generic_callback. type should actually be
> an enum, but one can't forward declare an enum, so as long as the
> internals are in public headers it won't be an enum.
>
> The typical implementation of such a callback would be with a switch:
>
> static int generic_callback(AVFormatContext *s, int type, void *priv1,
> void *priv2, int64_t num)
> {
> switch (type) {
> case FOO:
> return handle_foo(s, priv1, priv2, num);
> case BAR:
> return handle_bar(s, priv1, priv2, num);
> default:
> return AVERROR(ENOSYS);
> }
>
> The typical calling code would look like this:
>
> {
> if (!s->oformat->generic_callback)
> AVERROR(ENOSYS);
> /* In case this type needs so many arguments that
> * a structure for them is used they should be prepared here. */
> ret = s->oformat->generic_callback(s, type_foo, /* other arguments);
> /* Inspect ret or just return it; notice that ret may very well be
> AVERROR(ENOSYS) again, because the existence of the generic callback
> does not imply that every type is supported. */
> }
>
> There are more callbacks that should be moved into this generic callback
> besides the callbacks that you intend to add: The read_play and
> read_pause callbacks which are only supported by a single demuxer. E.g.
> av_read_play would look like this:
>
> int av_read_play(AVFormatContext *s)
> {
> if (s->iformat->generic_callback) {
> int ret = s->iformat->generic_callback(s, FF_CB_TYPE_READ_PLAY,
> NULL, NULL, 0);
> if (ret != AVERROR(ENOSYS))
> return ret;
> }
> if (s->pb)
> return avio_pause(s->pb, 0);
> return AVERROR(ENOSYS);
> }
Hi Andreas,
Thanks for chiming in! I have to agree with Hendrik, to me this is a
rather opaque, and thus hard to use, API.
https://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294747.html
provides another solution to the avformat/avdevice marriage, as based
on previous discussions (see links in
https://ffmpeg.org/pipermail/ffmpeg-devel/2022-March/294746.html).
Would yet another alternative be to have only a single field in
AVInput/OutputFormat, an opaque pointer void *avdevicecallbacks to a
new AVInputDevice/AVOutputDevice struct that is set when a format is a
device. These new types would live in avdevice and contain the
callback pointers that now live in AVInput/OutputFormat (and possibly
later other relevant things, perhaps a more generic name like void
*priv_avdevice would be good). (With my patches,) these callbacks are:
AVInputFormat:
int (*control_message)(struct AVFormatContext *s, int type,
void *data, size_t data_size);
int (*get_device_list)(struct AVFormatContext *s, struct
AVDeviceInfoList *device_list);
int (*create_device_capabilities)(struct AVFormatContext *s, struct
AVDeviceCapabilitiesQuery *caps);
int (*free_device_capabilities)(struct AVFormatContext *s, struct
AVDeviceCapabilitiesQuery *caps);
AVOutputFormat:
void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
int64_t *dts, int64_t *wall);
int (*control_message)(struct AVFormatContext *s, int type,
void *data, size_t data_size);
int (*get_device_list)(struct AVFormatContext *s, struct
AVDeviceInfoList *device_list);
int (*create_device_capabilities)(struct AVFormatContext *s, struct
AVDeviceCapabilitiesQuery *caps);
int (*free_device_capabilities)(struct AVFormatContext *s, struct
AVDeviceCapabilitiesQuery *caps);
Please let me know if i missed some.
That way any extension to avdevices would occur only in libavdevice,
while avdevices can still (__very conveniently!__) be pretend
formats--something that i think must be preserved.
This looks simple, am I forgetting something obvious?
(This does not remove HLSs read_play and read_pause callbacks, but
those aren't my concern ;) ).
The current patchset no longer applies to HEAD by the way, I'll send a
rebased one once we get a bit further in this discussion.
All the best,
Dee
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 08/21] avdevice/avdevice: clean up avdevice_capabilities_create
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (6 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 07/21] avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API" Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 09/21] avdevice: capabilities API details no longer public Diederick Niehorster
` (13 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Draw implementation in line with that of avdevice_list_devices
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index d367189532..2e8261e0d2 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -113,11 +113,14 @@ int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatConte
AVDictionary **device_options)
{
int ret;
- av_assert0(s && caps);
+ av_assert0(s);
+ av_assert0(caps);
av_assert0(s->iformat || s->oformat);
if ((s->oformat && !s->oformat->create_device_capabilities) ||
- (s->iformat && !s->iformat->create_device_capabilities))
+ (s->iformat && !s->iformat->create_device_capabilities)) {
+ *caps = NULL;
return AVERROR(ENOSYS);
+ }
*caps = av_mallocz(sizeof(**caps));
if (!(*caps))
return AVERROR(ENOMEM);
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 09/21] avdevice: capabilities API details no longer public
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (7 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 08/21] avdevice/avdevice: clean up avdevice_capabilities_create Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 10/21] avutil/opt: document AVOptionRange min_value > max_value Diederick Niehorster
` (12 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Bumping avdevice major version (API removed, even if it cannot have been used by anyone)
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 2 +-
libavdevice/avdevice.h | 28 +---------------------------
libavdevice/internal.h | 33 +++++++++++++++++++++++++++++++++
libavdevice/version.h | 2 +-
libavdevice/version_major.h | 2 +-
5 files changed, 37 insertions(+), 30 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 2e8261e0d2..1cc9cd3923 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -34,7 +34,7 @@ const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
#define V AV_OPT_FLAG_VIDEO_PARAM
#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x)
-const AVOption av_device_capabilities[] = {
+const AVOption ff_device_capabilities[] = {
{ "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT,
{.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V },
{ "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT,
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index 9724e7edf5..6d45c74616 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -416,33 +416,7 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
* avformat_free_context(oc);
* @endcode
*/
-
-/**
- * Structure describes device capabilities.
- *
- * It is used by devices in conjunction with av_device_capabilities AVOption table
- * to implement capabilities probing API based on AVOption API. Should not be used directly.
- */
-typedef struct AVDeviceCapabilitiesQuery {
- const AVClass *av_class;
- AVFormatContext *device_context;
- enum AVCodecID codec;
- enum AVSampleFormat sample_format;
- enum AVPixelFormat pixel_format;
- int sample_rate;
- int channels;
- int64_t channel_layout;
- int window_width;
- int window_height;
- int frame_width;
- int frame_height;
- AVRational fps;
-} AVDeviceCapabilitiesQuery;
-
-/**
- * AVOption table used by devices to implement device capabilities API. Should not be used by a user.
- */
-extern const AVOption av_device_capabilities[];
+typedef struct AVDeviceCapabilitiesQuery AVDeviceCapabilitiesQuery;
/**
* Initialize capabilities probing API based on AVOption API.
diff --git a/libavdevice/internal.h b/libavdevice/internal.h
index 67c90e1f87..bef3a4bd2d 100644
--- a/libavdevice/internal.h
+++ b/libavdevice/internal.h
@@ -19,10 +19,43 @@
#ifndef AVDEVICE_INTERNAL_H
#define AVDEVICE_INTERNAL_H
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/rational.h"
+#include "libavutil/samplefmt.h"
+#include "libavcodec/codec_id.h"
#include "libavformat/avformat.h"
av_warn_unused_result
int ff_alloc_input_device_context(struct AVFormatContext **avctx, const AVInputFormat *iformat,
const char *format);
+/**
+ * Structure describes device capabilities.
+ *
+ * It is used by devices in conjunction with ff_device_capabilities AVOption table
+ * to implement capabilities probing API based on AVOption API.
+ */
+struct AVDeviceCapabilitiesQuery {
+ const AVClass *av_class;
+ AVFormatContext *device_context;
+ enum AVCodecID codec;
+ enum AVSampleFormat sample_format;
+ enum AVPixelFormat pixel_format;
+ int sample_rate;
+ int channels;
+ int64_t channel_layout;
+ int window_width;
+ int window_height;
+ int frame_width;
+ int frame_height;
+ AVRational fps;
+};
+
+/**
+ * AVOption table used by devices to implement device capabilities API.
+ */
+extern const AVOption ff_device_capabilities[];
+
#endif
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 7c132f2174..09156778db 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -30,7 +30,7 @@
#include "version_major.h"
-#define LIBAVDEVICE_VERSION_MINOR 9
+#define LIBAVDEVICE_VERSION_MINOR 1
#define LIBAVDEVICE_VERSION_MICRO 100
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
diff --git a/libavdevice/version_major.h b/libavdevice/version_major.h
index d255ff6992..b32de7325d 100644
--- a/libavdevice/version_major.h
+++ b/libavdevice/version_major.h
@@ -25,7 +25,7 @@
* Libavdevice version macros
*/
-#define LIBAVDEVICE_VERSION_MAJOR 59
+#define LIBAVDEVICE_VERSION_MAJOR 60
/**
* FF_API_* defines may be placed below to indicate public API that will be
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 10/21] avutil/opt: document AVOptionRange min_value > max_value
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (8 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 09/21] avdevice: capabilities API details no longer public Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 11/21] avdevice: Add internal helpers for querying device capabilities Diederick Niehorster
` (11 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
AVOptionRange needs a way to encode that an option is not set. Here i
provide a documentation solution. When a range is invalid (value_min >
value_max), it should be considered unset/value not available.
When querying a range of formats of an avdevice, sometimes for a given
format the queried option is not available. This is not an error as the
user is asking for a valid capability, it just doesn't always apply to
all the matching formats of the device. This cannot be communicated
through a single special value (like 0 or -1) as that has the same
problem asany special value solution. Documenting that an invalid range
means value not available allows communicating this situation without
adding a field to the AVOptionRange struct.
This further documents that an AVOptionRange denotes a single value when
value_min == value_max, and a range only when value_max > value_min.
This makes the is_range field superfluous.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavutil/opt.c | 2 +-
libavutil/opt.h | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libavutil/opt.c b/libavutil/opt.c
index 8ffb10449b..ebffbb2f36 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -1979,9 +1979,9 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch
ranges->range[0] = range;
ranges->nb_ranges = 1;
ranges->nb_components = 1;
- range->is_range = 1;
range->value_min = field->min;
range->value_max = field->max;
+ range->is_range = field->max > field->min;
switch (field->type) {
case AV_OPT_TYPE_BOOL:
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 461b5d3b6b..4e7d7433e9 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -316,6 +316,11 @@ typedef struct AVOptionRange {
* Value range.
* For string ranges this represents the min/max length.
* For dimensions this represents the min/max pixel count or width/height in multi-component case.
+ * If value_min < value_max, the struct encodes a range.
+ * If value_min == value_max, the struct encodes a single value.
+ * If value_min > value_max, the range is empty (a value is not available).
+ * Good sentinel values to use when a range is empty
+ * are value_min=0, value_max=-1, but this is not required.
*/
double value_min, value_max;
/**
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 11/21] avdevice: Add internal helpers for querying device capabilities
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (9 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 10/21] avutil/opt: document AVOptionRange min_value > max_value Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 12/21] avdevice: change device capabilities option type Diederick Niehorster
` (10 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/internal.h | 31 +++++++++++++++++++++++++++
libavdevice/utils.c | 48 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/libavdevice/internal.h b/libavdevice/internal.h
index bef3a4bd2d..eee493a4c7 100644
--- a/libavdevice/internal.h
+++ b/libavdevice/internal.h
@@ -58,4 +58,35 @@ struct AVDeviceCapabilitiesQuery {
*/
extern const AVOption ff_device_capabilities[];
+/**
+ * Enumeration indicating which device capability is being queried.
+ */
+enum AVDeviceCapabilitiesQueryType {
+ AV_DEV_CAP_QUERY_NONE = 0,
+ // both audio and video
+ AV_DEV_CAP_QUERY_CODEC,
+ // audio
+ AV_DEV_CAP_QUERY_SAMPLE_FORMAT,
+ AV_DEV_CAP_QUERY_SAMPLE_RATE,
+ AV_DEV_CAP_QUERY_CHANNELS,
+ AV_DEV_CAP_QUERY_CHANNEL_LAYOUT,
+ // video
+ AV_DEV_CAP_QUERY_PIXEL_FORMAT,
+ AV_DEV_CAP_QUERY_WINDOW_SIZE,
+ AV_DEV_CAP_QUERY_FRAME_SIZE,
+ AV_DEV_CAP_QUERY_FPS
+};
+
+/**
+ * Find AVDeviceCapabilitiesQueryType enumeration by means of options name.
+ * Returns AV_DEV_CAP_QUERY_NONE if not found.
+ */
+enum AVDeviceCapabilitiesQueryType ff_device_get_query_type(const char* option_name);
+
+/**
+ * Get component name from AVDeviceCapabilitiesQueryType enumeration and component index.
+ * (Some options have multiple components, e.g. AV_DEV_CAP_QUERY_FRAME_SIZE).
+ */
+const char* ff_device_get_query_component_name(enum AVDeviceCapabilitiesQueryType query_type, int component);
+
#endif
diff --git a/libavdevice/utils.c b/libavdevice/utils.c
index d9a52c53ab..de9023f215 100644
--- a/libavdevice/utils.c
+++ b/libavdevice/utils.c
@@ -19,6 +19,7 @@
#include "internal.h"
#include "libavutil/opt.h"
#include "libavformat/avformat.h"
+#include "libavutil/avassert.h"
int ff_alloc_input_device_context(AVFormatContext **avctx, const AVInputFormat *iformat, const char *format)
{
@@ -57,3 +58,50 @@ int ff_alloc_input_device_context(AVFormatContext **avctx, const AVInputFormat *
avformat_free_context(s);
return ret;
}
+
+typedef struct AVDeviceCapabilitiesQueryTypeEntry {
+ const char* name;
+ enum AVDeviceCapabilitiesQueryType query_type;
+} AVDeviceCapabilitiesQueryTypeEntry;
+
+static const AVDeviceCapabilitiesQueryTypeEntry query_table[] = {
+ // both audio and video
+ { "codec", AV_DEV_CAP_QUERY_CODEC },
+ // audio
+ { "sample_format", AV_DEV_CAP_QUERY_SAMPLE_FORMAT },
+ { "sample_rate", AV_DEV_CAP_QUERY_SAMPLE_RATE },
+ { "channels", AV_DEV_CAP_QUERY_CHANNELS },
+ { "channel_layout", AV_DEV_CAP_QUERY_CHANNEL_LAYOUT },
+ // video
+ { "pixel_format", AV_DEV_CAP_QUERY_PIXEL_FORMAT },
+ { "frame_size", AV_DEV_CAP_QUERY_FRAME_SIZE },
+ { "window_size", AV_DEV_CAP_QUERY_WINDOW_SIZE },
+ { "fps", AV_DEV_CAP_QUERY_FPS },
+};
+
+enum AVDeviceCapabilitiesQueryType ff_device_get_query_type(const char* option_name)
+{
+ for (int i = 0; i < FF_ARRAY_ELEMS(query_table); ++i) {
+ if (!strcmp(query_table[i].name, option_name))
+ return query_table[i].query_type;
+ }
+ // not found
+ return AV_DEV_CAP_QUERY_NONE;
+}
+
+const char* ff_device_get_query_component_name(enum AVDeviceCapabilitiesQueryType query_type, int component)
+{
+ if (query_type == AV_DEV_CAP_QUERY_WINDOW_SIZE || query_type == AV_DEV_CAP_QUERY_FRAME_SIZE) {
+ // special case: different name for each component
+ return component == 0 ? "pixel_count" : (component == 1 ? "width" : (component == 2 ? "height" : ""));
+ }
+ else {
+ av_assert0(component == 0);
+ for (int i = 0; i < FF_ARRAY_ELEMS(query_table); ++i) {
+ if (query_table[i].query_type == query_type)
+ return query_table[i].name;
+ }
+ }
+ // not found
+ return NULL;
+}
\ No newline at end of file
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 12/21] avdevice: change device capabilities option type
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (10 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 11/21] avdevice: Add internal helpers for querying device capabilities Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 13/21] avdevice: improve capabilities' option API Diederick Niehorster
` (9 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Changes fps option from AVRational to double. This since any device
capability query results are returned in AVOptionRanges, which hold the
value as doubles, which can't contain AVRationals.
Also updated documentation of other capabilities, some had the wrong
option type listed.
micro version bump as this capabilities API is unused for now.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 4 ++--
libavdevice/avdevice.h | 6 +++---
libavdevice/internal.h | 4 +++-
libavdevice/version.h | 2 +-
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 1cc9cd3923..863f8df477 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -51,8 +51,8 @@ const AVOption ff_device_capabilities[] = {
{.str = NULL}, -1, INT_MAX, E|D|V },
{ "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE,
{.str = NULL}, -1, INT_MAX, E|D|V },
- { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL,
- {.dbl = -1}, -1, INT_MAX, E|D|V },
+ { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_DOUBLE,
+ {.dbl = NAN}, 0, INT_MAX, E|D|V },
{ NULL }
};
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index 6d45c74616..a815d65f12 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -360,7 +360,7 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
* type: AV_OPT_TYPE_INT (AVCodecID value)
* - Capabilities valid for audio devices:
* - sample_format: supported sample formats.
- * type: AV_OPT_TYPE_INT (AVSampleFormat value)
+ * type: AV_OPT_TYPE_SAMPLE_FMT
* - sample_rate: supported sample rates.
* type: AV_OPT_TYPE_INT
* - channels: supported number of channels.
@@ -369,13 +369,13 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
* type: AV_OPT_TYPE_INT64
* - Capabilities valid for video devices:
* - pixel_format: supported pixel formats.
- * type: AV_OPT_TYPE_INT (AVPixelFormat value)
+ * type: AV_OPT_TYPE_PIXEL_FMT
* - window_size: supported window sizes (describes size of the window size presented to the user).
* type: AV_OPT_TYPE_IMAGE_SIZE
* - frame_size: supported frame sizes (describes size of provided video frames).
* type: AV_OPT_TYPE_IMAGE_SIZE
* - fps: supported fps values
- * type: AV_OPT_TYPE_RATIONAL
+ * type: AV_OPT_TYPE_DOUBLE
*
* Value of the capability may be set by user using av_opt_set() function
* and AVDeviceCapabilitiesQuery object. Following queries will
diff --git a/libavdevice/internal.h b/libavdevice/internal.h
index eee493a4c7..5f0bd403dd 100644
--- a/libavdevice/internal.h
+++ b/libavdevice/internal.h
@@ -50,7 +50,9 @@ struct AVDeviceCapabilitiesQuery {
int window_height;
int frame_width;
int frame_height;
- AVRational fps;
+ // NB: an AVRational cannot be represented in the AVOptionRange
+ // output of av_opt_query_ranges, so we store fps as double instead
+ double fps;
};
/**
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 09156778db..181987d287 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
#define LIBAVDEVICE_VERSION_MINOR 1
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 13/21] avdevice: improve capabilities' option API
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (11 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 12/21] avdevice: change device capabilities option type Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 14/21] avdevice/dshow: move audio format helpers Diederick Niehorster
` (8 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
This adds avdevice_capabilities_get_class() to allow examining the
capabilities that can be queried/set through the capabilities API, and
avdevice_capabilities_bprint_num() which allows printing the value
returned when querying a capability. These values (min_value and
max_value of an AVOptionRange) are doubles and this function formats
them properly, e.g. 1. for a AV_OPT_TYPE_PIXEL_FMT -> yuyv422.
bump minor version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/avdevice.c | 80 ++++++++++++++++++++++++++++++++++++++++++
libavdevice/avdevice.h | 27 ++++++++++++++
libavdevice/version.h | 4 +--
3 files changed, 109 insertions(+), 2 deletions(-)
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 863f8df477..e2c60618d3 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -19,6 +19,9 @@
#include "libavutil/avassert.h"
#include "libavutil/samplefmt.h"
#include "libavutil/pixfmt.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/avutil.h"
+#include "libavcodec/codec_id.h"
#include "libavformat/version.h"
#include "avdevice.h"
#include "internal.h"
@@ -141,6 +144,83 @@ int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatConte
return ret;
}
+static const AVClass avdevice_capabilities_context_class = {
+ .class_name = "AVDeviceCapabilitiesQuery",
+ .item_name = av_default_item_name,
+ .option = ff_device_capabilities,
+ .version = LIBAVUTIL_VERSION_INT
+};
+
+const AVClass *avdevice_capabilities_get_class(void)
+{
+ return &avdevice_capabilities_context_class;
+}
+
+int avdevice_capabilities_bprint_num(AVBPrint *bp, const char *name, double val)
+{
+ int opt_type_set = 0, is_codec = 0;
+ enum AVOptionType type; // will be set below, opt_type_set tracks if has been set
+ const AVClass *cap_class = avdevice_capabilities_get_class();
+
+ // may fail, e.g. if name of a component of a multi-component option was provided as input
+ const AVOption *field = av_opt_find(&cap_class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ);
+ if (field) {
+ type = field->type;
+ opt_type_set = 1;
+ }
+
+ // based on name, a type override or other extra info may be needed
+ if (opt_type_set && type==AV_OPT_TYPE_INT && strcmp(name, "codec")==0)
+ is_codec = 1;
+ // next three are for the three components of a AV_OPT_TYPE_IMAGE_SIZE
+ // NB: these wont be found by av_opt_find above
+ else if (
+ strcmp(name, ff_device_get_query_component_name(AV_DEV_CAP_QUERY_WINDOW_SIZE, 0))==0 ||
+ strcmp(name, ff_device_get_query_component_name(AV_DEV_CAP_QUERY_WINDOW_SIZE, 1))==0 ||
+ strcmp(name, ff_device_get_query_component_name(AV_DEV_CAP_QUERY_WINDOW_SIZE, 2))==0
+ ) {
+ type = AV_OPT_TYPE_INT;
+ opt_type_set = 1;
+ }
+
+ // now, format if type set, else error
+ if (!opt_type_set) {
+ av_log(NULL, AV_LOG_ERROR, "A device capability with the name '%s' is not known\n", name);
+ return AVERROR_OPTION_NOT_FOUND;
+ }
+
+ switch (type)
+ {
+ case AV_OPT_TYPE_INT:
+ {
+ int temp = lrint(val);
+ if (is_codec)
+ av_bprintf(bp, "%s", (char *)avcodec_get_name((enum AVCodecID)lrint(val)));
+ else
+ av_bprintf(bp, "%d", temp);
+ break;
+ }
+ case AV_OPT_TYPE_PIXEL_FMT:
+ av_bprintf(bp, "%s", (char *)av_x_if_null(av_get_pix_fmt_name((enum AVPixelFormat)lrint(val)), "none"));
+ break;
+ case AV_OPT_TYPE_SAMPLE_FMT:
+ av_bprintf(bp, "%s", (char *)av_x_if_null(av_get_sample_fmt_name((enum AVSampleFormat)lrint(val)), "none"));
+ break;
+ case AV_OPT_TYPE_DOUBLE:
+ av_bprintf(bp, "%f", val);
+ break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ av_bprintf(bp, "0x%"PRIx64, llrint(val));
+ break;
+
+ default:
+ av_log(NULL, AV_LOG_ERROR, "avdevice_capabilities_bprint_num is not implemented for this option type\n", name);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ return 0;
+}
+
void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s)
{
if (!s || !caps || !(*caps))
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index a815d65f12..5f9dfccc34 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -64,6 +64,7 @@
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/dict.h"
+#include "libavutil/bprint.h"
#include "libavformat/avformat.h"
/**
@@ -418,6 +419,16 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
*/
typedef struct AVDeviceCapabilitiesQuery AVDeviceCapabilitiesQuery;
+/**
+ * Get the AVClass for AVDeviceCapabilitiesQuery. It can be used
+ * in combination with AV_OPT_SEARCH_FAKE_OBJ for examining
+ * which capabilities can be queried through the
+ * AVDeviceCapabilitiesQuery API.
+ *
+ * @see av_opt_find(), av_opt_next().
+ */
+const AVClass *avdevice_capabilities_get_class(void);
+
/**
* Initialize capabilities probing API based on AVOption API.
*
@@ -438,6 +449,22 @@ typedef struct AVDeviceCapabilitiesQuery AVDeviceCapabilitiesQuery;
int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
AVDictionary **device_options);
+/**
+ * Format a capabilities value as string and append to a bprint buffer.
+ * @param bp A buffer to which the output string will be
+ * appended.
+ * @param name Name of the option to print (provide
+ * AVOptionRange.str).
+ * @param val An capabilities value represented as a
+ * double (e.g. min_value or max_value of
+ * AVOptionRange)
+ * @return 0 on success, a negative error code otherwise. Even if
+ * return value indicates success, the state of the bp variable
+ * should also be checked, as it may have experienced memory allocation
+ * trouble.
+ */
+int avdevice_capabilities_bprint_num(AVBPrint *bp, const char *name, double val);
+
/**
* Free resources created by avdevice_capabilities_create()
*
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 181987d287..764aceccb5 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -30,8 +30,8 @@
#include "version_major.h"
-#define LIBAVDEVICE_VERSION_MINOR 1
-#define LIBAVDEVICE_VERSION_MICRO 101
+#define LIBAVDEVICE_VERSION_MINOR 2
+#define LIBAVDEVICE_VERSION_MICRO 100
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 14/21] avdevice/dshow: move audio format helpers
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (12 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 13/21] avdevice: improve capabilities' option API Diederick Niehorster
@ 2022-03-30 12:17 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 15/21] avdevice/dshow: when closing, set context fields back to zero Diederick Niehorster
` (7 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Needs to be moved up in file for upcoming implementation of
avdevice_capabilities_create.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index a780351170..d35224beb5 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -79,6 +79,26 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
return avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, biCompression); // all others
}
+static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
+{
+ switch (sample_fmt) {
+ case AV_SAMPLE_FMT_U8: return AV_CODEC_ID_PCM_U8;
+ case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
+ case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
+ default: return AV_CODEC_ID_NONE; /* Should never happen. */
+ }
+}
+
+static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
+{
+ switch (bits) {
+ case 8: return AV_SAMPLE_FMT_U8;
+ case 16: return AV_SAMPLE_FMT_S16;
+ case 32: return AV_SAMPLE_FMT_S32;
+ default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
+ }
+}
+
static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info)
{
switch (fmt_info->NominalRange)
@@ -1610,26 +1630,6 @@ static int dshow_control_message(AVFormatContext *avctx, int type, void *data, s
return ret;
}
-static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
-{
- switch (sample_fmt) {
- case AV_SAMPLE_FMT_U8: return AV_CODEC_ID_PCM_U8;
- case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
- case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
- default: return AV_CODEC_ID_NONE; /* Should never happen. */
- }
-}
-
-static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
-{
- switch (bits) {
- case 8: return AV_SAMPLE_FMT_U8;
- case 16: return AV_SAMPLE_FMT_S16;
- case 32: return AV_SAMPLE_FMT_S32;
- default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
- }
-}
-
static int
dshow_add_device(AVFormatContext *avctx,
enum dshowDeviceType devtype)
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 15/21] avdevice/dshow: when closing, set context fields back to zero
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (13 preceding siblings ...)
2022-03-30 12:17 ` [FFmpeg-devel] [PATCH v5 14/21] avdevice/dshow: move audio format helpers Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 16/21] avdevice/dshow: implement capabilities API Diederick Niehorster
` (6 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
After the avdevice capabilities API is implemented, the format context
may be reused after querying device capabilities in a later
avformat_open_input call. To enable this reuse, after releasing
resources, make sure to also set the corresponding pointers back to
NULL. This correctly indicates their state after cleanup.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index d35224beb5..0d5f731030 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -264,14 +264,18 @@ dshow_read_close(AVFormatContext *s)
ICaptureGraphBuilder2_Release(ctx->graph_builder2[VideoDevice]);
if (ctx->graph_builder2[AudioDevice])
ICaptureGraphBuilder2_Release(ctx->graph_builder2[AudioDevice]);
+ ctx->graph_builder2[0] = NULL;
+ ctx->graph_builder2[1] = NULL;
if (ctx->control) {
IMediaControl_Stop(ctx->control);
IMediaControl_Release(ctx->control);
}
+ ctx->control = NULL;
if (ctx->media_event)
IMediaEvent_Release(ctx->media_event);
+ ctx->media_event = NULL;
if (ctx->graph) {
IEnumFilters *fenum;
@@ -289,25 +293,34 @@ dshow_read_close(AVFormatContext *s)
IEnumFilters_Release(fenum);
}
IGraphBuilder_Release(ctx->graph);
+ ctx->graph = NULL;
}
if (ctx->capture_pin[VideoDevice])
ff_dshow_pin_Release(ctx->capture_pin[VideoDevice]);
if (ctx->capture_pin[AudioDevice])
ff_dshow_pin_Release(ctx->capture_pin[AudioDevice]);
+ ctx->capture_pin[0] = NULL;
+ ctx->capture_pin[1] = NULL;
if (ctx->capture_filter[VideoDevice])
ff_dshow_filter_Release(ctx->capture_filter[VideoDevice]);
if (ctx->capture_filter[AudioDevice])
ff_dshow_filter_Release(ctx->capture_filter[AudioDevice]);
+ ctx->capture_filter[0] = NULL;
+ ctx->capture_filter[1] = NULL;
if (ctx->device_pin[VideoDevice])
IPin_Release(ctx->device_pin[VideoDevice]);
if (ctx->device_pin[AudioDevice])
IPin_Release(ctx->device_pin[AudioDevice]);
+ ctx->device_pin[0] = NULL;
+ ctx->device_pin[1] = NULL;
if (ctx->device_filter[VideoDevice])
IBaseFilter_Release(ctx->device_filter[VideoDevice]);
if (ctx->device_filter[AudioDevice])
IBaseFilter_Release(ctx->device_filter[AudioDevice]);
+ ctx->device_filter[0] = NULL;
+ ctx->device_filter[1] = NULL;
av_freep(&ctx->device_name[0]);
av_freep(&ctx->device_name[1]);
@@ -316,10 +329,13 @@ dshow_read_close(AVFormatContext *s)
if(ctx->mutex)
CloseHandle(ctx->mutex);
+ ctx->mutex = NULL;
if(ctx->event[0])
CloseHandle(ctx->event[0]);
if(ctx->event[1])
CloseHandle(ctx->event[1]);
+ ctx->event[0] = NULL;
+ ctx->event[1] = NULL;
pktl = ctx->pktl;
while (pktl) {
@@ -328,6 +344,7 @@ dshow_read_close(AVFormatContext *s)
av_free(pktl);
pktl = next;
}
+ ctx->pktl = NULL;
CoUninitialize();
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 16/21] avdevice/dshow: implement capabilities API
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (14 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 15/21] avdevice/dshow: when closing, set context fields back to zero Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 17/21] avdevice/dshow: cosmetics Diederick Niehorster
` (5 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
This implements avdevice_capabilities_create and
avdevice_capabilities_free for the dshow device.
This enables configuration discovery of DirectShow devices through the
API, which is important for my use case. It enables making proper GUIs
presenting users with options, instead of asking them to discover a
dshow device's capabilities through the list_options option with an
FFmpeg tool, and listing what they want to configure in dumb text boxes.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 430 ++++++++++++++++++++++++++++++++++++++++--
libavdevice/version.h | 2 +-
2 files changed, 412 insertions(+), 20 deletions(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 0d5f731030..58476a0f40 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -27,6 +27,7 @@
#include "libavformat/internal.h"
#include "libavformat/riff.h"
#include "avdevice.h"
+#include "internal.h"
#include "libavcodec/raw.h"
#include "objidl.h"
#include "shlwapi.h"
@@ -830,11 +831,15 @@ static void dshow_get_default_format(IPin *pin, IAMStreamConfig *config, enum ds
* try to set parameters specified through AVOptions, or the pin's
* default format if no such parameters were set. If successful,
* return 1 in *pformat_set.
- * If pformat_set is NULL, list all pin capabilities.
+ * If pformat_set is NULL or the ranges input is not NULL, list all
+ * pin capabilities.
+ * When listing pin capabilities, if ranges is NULL, output to log,
+ * else store capabilities in ranges.
*/
static void
dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
- IPin *pin, int *pformat_set)
+ IPin *pin, int *pformat_set,
+ AVOptionRanges *ranges, enum AVDeviceCapabilitiesQueryType query_type)
{
struct dshow_ctx *ctx = avctx->priv_data;
IAMStreamConfig *config = NULL;
@@ -878,7 +883,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
* one, with most info exposed (see comment below).
*/
use_default = !dshow_should_set_format(avctx, devtype);
- if (use_default && pformat_set)
+ if (use_default && pformat_set && !ranges)
{
// get default
dshow_get_default_format(pin, config, devtype, &type);
@@ -924,7 +929,9 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
// exposes contains a VIDEOINFOHEADER2. Fall back to the VIDEOINFOHEADER
// format if no corresponding VIDEOINFOHEADER2 is found when we finish
// iterating.
- for (i = 0; i < n && !format_set; i++) {
+ for (i = 0; i < n && (!format_set || ranges); i++) {
+ AVOptionRange *new_range[3] = { NULL };
+ int nb_range = 0;
struct dshow_format_info *fmt_info = NULL;
r = IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
if (r != S_OK)
@@ -960,7 +967,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
wait_for_better = 0;
}
- if (!pformat_set) {
+ if (!pformat_set && !ranges) {
const char *chroma = av_chroma_location_name(fmt_info->chroma_loc);
if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) {
const AVCodec *codec = avcodec_find_decoder(fmt_info->codec_id);
@@ -1024,6 +1031,60 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
bih->biWidth = requested_width;
bih->biHeight = requested_height;
}
+
+ if (ranges) {
+ for (int j = 0; j < ranges->nb_components; j++) {
+ new_range[j] = av_mallocz(sizeof(**new_range));
+ if (!new_range[j])
+ goto next;
+ new_range[j]->value_max = -1.; // init (min:0, max:-1 means value not set)
+ ++nb_range;
+
+ switch (query_type)
+ {
+ case AV_DEV_CAP_QUERY_CODEC:
+ if (dshow_pixfmt(bih->biCompression, bih->biBitCount) == AV_PIX_FMT_NONE) {
+ const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
+ new_range[j]->value_min = av_codec_get_id(tags, bih->biCompression);
+ }
+ else
+ new_range[j]->value_min = AV_CODEC_ID_RAWVIDEO;
+ new_range[j]->value_max = new_range[j]->value_min;
+ break;
+ case AV_DEV_CAP_QUERY_PIXEL_FORMAT:
+ new_range[j]->value_min = new_range[j]->value_max = dshow_pixfmt(bih->biCompression, bih->biBitCount);
+ new_range[j]->value_min;
+ break;
+ case AV_DEV_CAP_QUERY_FRAME_SIZE:
+ {
+ switch (j)
+ {
+ case 0:
+ new_range[j]->value_min = vcaps->MinOutputSize.cx * vcaps->MinOutputSize.cy;
+ new_range[j]->value_max = vcaps->MaxOutputSize.cx * vcaps->MaxOutputSize.cy;
+ break;
+ case 1:
+ new_range[j]->value_min = vcaps->MinOutputSize.cx;
+ new_range[j]->value_max = vcaps->MaxOutputSize.cx;
+ break;
+ case 2:
+ new_range[j]->value_min = vcaps->MinOutputSize.cy;
+ new_range[j]->value_max = vcaps->MaxOutputSize.cy;
+ break;
+ }
+ break;
+ }
+ case AV_DEV_CAP_QUERY_FPS:
+ new_range[j]->value_min = 1e7 / vcaps->MaxFrameInterval;
+ new_range[j]->value_max = 1e7 / vcaps->MinFrameInterval;
+ break;
+
+ // default:
+ // an audio property is being queried, output all fields 0 (mallocz above) is fine
+ }
+ }
+ }
+
} else {
WAVEFORMATEX *fx;
AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
@@ -1035,7 +1096,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
} else {
goto next;
}
- if (!pformat_set) {
+ if (!pformat_set && !ranges) {
av_log(
avctx,
AV_LOG_INFO,
@@ -1051,15 +1112,69 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
) {
goto next;
}
+
+ if (ranges) {
+ for (int j = 0; j < ranges->nb_components; j++) {
+ new_range[j] = av_mallocz(sizeof(**new_range));
+ if (!new_range[j])
+ goto next;
+ new_range[j]->value_max = -1.; // init (min:0, max:-1 means value not set)
+ ++nb_range;
+
+ switch (query_type)
+ {
+ case AV_DEV_CAP_QUERY_SAMPLE_FORMAT:
+ new_range[j]->value_min = sample_fmt_bits_per_sample(acaps->MinimumBitsPerSample);
+ new_range[j]->value_max = sample_fmt_bits_per_sample(acaps->MaximumBitsPerSample);
+ break;
+ case AV_DEV_CAP_QUERY_SAMPLE_RATE:
+ new_range[j]->value_min = acaps->MinimumSampleFrequency;
+ new_range[j]->value_max = acaps->MaximumSampleFrequency;
+ break;
+ case AV_DEV_CAP_QUERY_CHANNELS:
+ new_range[j]->value_min = acaps->MinimumChannels;
+ new_range[j]->value_max = acaps->MaximumChannels;
+ break;
+
+ // default:
+ // a video property is being queried, output all fields 0 (mallocz above) is fine
+ // NB: this is a for-loop since some of the video queries are multi-component
+ // and all components should be set
+ }
+ }
+ }
}
// found a matching format. Either apply or store
// for safekeeping if we might maybe find a better
// format with more info attached to it (see comment
- // above loop)
- if (!wait_for_better) {
+ // above loop). If storing all capabilities of device
+ // in ranges, try to apply in all cases, and store
+ // caps if successfully applied
+ if (!wait_for_better || ranges) {
if (IAMStreamConfig_SetFormat(config, type) != S_OK)
goto next;
+ else if (ranges) {
+ // format matched and could be set successfully.
+ // fill in some fields for each capability
+ for (int j = 0; j < nb_range; j++) {
+ new_range[j]->str = av_strdup(ff_device_get_query_component_name(query_type, j));
+ if (!new_range[j]->str)
+ goto next;
+ new_range[j]->is_range = new_range[j]->value_min < new_range[j]->value_max;
+ }
+
+ // store to ranges output
+ if (av_reallocp_array(&ranges->range,
+ ranges->nb_ranges * ranges->nb_components + nb_range * ranges->nb_components,
+ sizeof(*ranges->range)) < 0)
+ goto next;
+ for (int j = 0; j < nb_range; ++j) {
+ ranges->range[ranges->nb_ranges] = new_range[j];
+ ranges->nb_ranges++;
+ new_range[j] = NULL; // copied into array, make sure not freed below
+ }
+ }
format_set = 1;
}
else if (!previous_match_type) {
@@ -1070,6 +1185,12 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
}
next:
av_freep(&fmt_info);
+ for (int j = 0; j < nb_range; ++j) {
+ if (new_range[j]) {
+ av_freep(&new_range[j]->str);
+ av_freep(&new_range[j]);
+ }
+ }
if (type && type->pbFormat)
CoTaskMemFree(type->pbFormat);
CoTaskMemFree(type);
@@ -1209,10 +1330,13 @@ end:
* devtype, retrieve the first output pin and return the pointer to the
* object found in *ppin.
* If ppin is NULL, cycle through all pins listing audio/video capabilities.
+ * If ppin is not NULL and ranges is also not null, enumerate all formats
+ * supported by the selected pin.
*/
static int
dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
- enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, IPin **ppin)
+ enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter,
+ IPin **ppin, AVOptionRanges *ranges, enum AVDeviceCapabilitiesQueryType query_type)
{
struct dshow_ctx *ctx = avctx->priv_data;
IEnumPins *pins = 0;
@@ -1250,6 +1374,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
wchar_t *pin_id = NULL;
char *pin_buf = NULL;
char *desired_pin_name = devtype == VideoDevice ? ctx->video_pin_name : ctx->audio_pin_name;
+ int nb_ranges = ranges ? ranges->nb_ranges : 0;
IPin_QueryPinInfo(pin, &info);
IBaseFilter_Release(info.pFilter);
@@ -1274,7 +1399,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
if (!ppin) {
av_log(avctx, AV_LOG_INFO, " Pin \"%s\" (alternative pin name \"%s\")\n", name_buf, pin_buf);
- dshow_cycle_formats(avctx, devtype, pin, NULL);
+ dshow_cycle_formats(avctx, devtype, pin, NULL, NULL, AV_DEV_CAP_QUERY_NONE);
goto next;
}
@@ -1288,12 +1413,15 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
// will either try to find format matching options supplied by user
// or try to open default format. Successful if returns with format_set==1
- dshow_cycle_formats(avctx, devtype, pin, &format_set);
+ // if ranges is non-NULL, will iterate over all formats and return info
+ // about all the valid ones. If any valid found, format_set==1, else
+ // format_set will be 0
+ dshow_cycle_formats(avctx, devtype, pin, &format_set, ranges, query_type);
if (!format_set) {
goto next;
}
- if (devtype == AudioDevice && ctx->audio_buffer_size) {
+ if (devtype == AudioDevice && ctx->audio_buffer_size && !ranges) {
if (dshow_set_audio_buffer_size(avctx, pin) < 0) {
av_log(avctx, AV_LOG_ERROR, "unable to set audio buffer size %d to pin, using pin anyway...", ctx->audio_buffer_size);
}
@@ -1306,8 +1434,25 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
next:
if (p)
IKsPropertySet_Release(p);
- if (device_pin != pin)
+ if (device_pin != pin) {
IPin_Release(pin);
+ // remove any option ranges info we just added, wrong pin
+ if (ranges && nb_ranges>0) {
+ int nb_original_entries = nb_ranges * ranges->nb_components;
+ for (int i = nb_original_entries; i < ranges->nb_ranges * ranges->nb_components; i++) {
+ AVOptionRange *range = ranges->range[i];
+ if (range) {
+ av_freep(&range->str);
+ av_freep(&ranges->range[i]);
+ }
+ }
+ if (av_reallocp_array(&ranges->range, nb_original_entries, sizeof(*ranges->range)) < 0)
+ ranges->nb_ranges = 0;
+ else
+ ranges->nb_ranges = nb_ranges;
+ }
+ device_pin = NULL;
+ }
av_free(name_buf);
av_free(pin_buf);
if (pin_id)
@@ -1339,10 +1484,12 @@ next:
*/
static int
dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
- enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
+ enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype,
+ AVOptionRanges *ranges, enum AVDeviceCapabilitiesQueryType query_type)
{
struct dshow_ctx *ctx = avctx->priv_data;
IBaseFilter *device_filter = NULL;
+ IPin *device_pin = NULL;
char *device_unique_name = NULL;
int r;
@@ -1350,7 +1497,7 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
return r;
ctx->device_filter[devtype] = device_filter;
ctx->device_unique_name[devtype] = device_unique_name;
- if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0)
+ if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, ranges ? &device_pin : NULL, ranges, query_type)) < 0)
return r;
return 0;
}
@@ -1433,7 +1580,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
goto error;
}
- if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, &device_pin)) < 0) {
+ if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, &device_pin, NULL, AV_DEV_CAP_QUERY_NONE)) < 0) {
ret = r;
goto error;
}
@@ -1856,14 +2003,14 @@ static int dshow_read_header(AVFormatContext *avctx)
}
if (ctx->list_options) {
if (ctx->device_name[VideoDevice])
- if ((r = dshow_list_device_options(avctx, devenum, VideoDevice, VideoSourceDevice))) {
+ if ((r = dshow_list_device_options(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, AV_DEV_CAP_QUERY_NONE))) {
ret = r;
goto error;
}
if (ctx->device_name[AudioDevice]) {
- if (dshow_list_device_options(avctx, devenum, AudioDevice, AudioSourceDevice)) {
+ if (dshow_list_device_options(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, AV_DEV_CAP_QUERY_NONE)) {
/* show audio options from combined video+audio sources as fallback */
- if ((r = dshow_list_device_options(avctx, devenum, AudioDevice, VideoSourceDevice))) {
+ if ((r = dshow_list_device_options(avctx, devenum, AudioDevice, VideoSourceDevice, NULL, AV_DEV_CAP_QUERY_NONE))) {
ret = r;
goto error;
}
@@ -2010,6 +2157,249 @@ static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
return ctx->eof ? AVERROR(EIO) : pkt->size;
}
+// TODO: consider if and how to expose extra info we have about formats, such as color_range
+static int dshow_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
+{
+ AVDeviceCapabilitiesQuery *caps = obj;
+ const AVFormatContext *avctx = caps->device_context;
+ struct dshow_ctx *ctx = avctx->priv_data;
+
+ int backup_sample_size;
+ int backup_sample_rate;
+ int backup_channels;
+ enum AVCodecID backup_video_codec_id;
+ enum AVPixelFormat backup_pixel_format;
+ int backup_requested_width;
+ int backup_requested_height;
+ char* backup_framerate = NULL;
+
+ enum AVDeviceCapabilitiesQueryType query_type = AV_DEV_CAP_QUERY_NONE;
+
+ AVOptionRanges *ranges = av_mallocz(sizeof(**ranges_arg));
+ const AVOption *field = av_opt_find(obj, key, NULL, 0, flags);
+ int ret;
+
+ ICreateDevEnum *devenum = NULL;
+
+ *ranges_arg = NULL;
+
+ if (!ranges) {
+ ret = AVERROR(ENOMEM);
+ goto fail1;
+ }
+
+ if (!field) {
+ ret = AVERROR_OPTION_NOT_FOUND;
+ goto fail1;
+ }
+
+ // turn option name into cap query
+ query_type = ff_device_get_query_type(field->name);
+
+ if (query_type == AV_DEV_CAP_QUERY_CHANNEL_LAYOUT || query_type == AV_DEV_CAP_QUERY_WINDOW_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "Querying the option %s is not supported for a dshow device\n", field->name);
+ ret = AVERROR(EINVAL);
+ goto fail1;
+ }
+
+ // take backup of dshow parameters/options
+ // audio
+ backup_sample_size = ctx->sample_size;
+ backup_sample_rate = ctx->sample_rate;
+ backup_channels = ctx->channels;
+ // video
+ backup_video_codec_id = ctx->video_codec_id;
+ backup_pixel_format = ctx->pixel_format;
+ backup_requested_width = ctx->requested_width;
+ backup_requested_height= ctx->requested_height;
+ backup_framerate = ctx->framerate;
+
+
+ // set format constraints set in AVDeviceCapabilitiesQuery
+ // audio (NB: channel_layout not used)
+ ctx->sample_size = av_get_bytes_per_sample(caps->sample_format) << 3;
+ ctx->sample_rate = (caps->sample_rate == -1) ? 0 : caps->sample_rate;
+ ctx->channels = (caps->channels == -1) ? 0 : caps->channels;
+ // video (NB: window_width and window_height not used)
+ ctx->video_codec_id = caps->codec;
+ ctx->pixel_format = caps->pixel_format;
+ ctx->requested_width = caps->frame_width;
+ ctx->requested_height = caps->frame_height;
+ // dshow checks whether requested framerate is set by means of !ctx->framerate.
+ // fill with something
+ if (!isnan(caps->fps)) {
+ ctx->requested_framerate = av_d2q(caps->fps, INT_MAX);
+ ctx->framerate = av_strdup("dummy"); // just make sure its non-zero
+ if (!ctx->framerate) {
+ ret = AVERROR(ENOMEM);
+ goto fail2;
+ }
+ }
+ else
+ ctx->framerate = NULL; // make sure its NULL (if it wasn't, we already have a backup of the pointer to restore later)
+
+ // now iterate matching format of pin that would be selected when device
+ // is opened with options currently in effect.
+ // for each matching format, output its parameter range, also if that same
+ // range already returned for another format. That way, user can reconstruct
+ // possible valid combinations by av_opt_query_ranges() for each of the
+ // format options and matching returned values by sequence number.
+ if (CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ICreateDevEnum, (void **) &devenum)) {
+ av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
+ ret = AVERROR(EIO);
+ goto fail2;
+ }
+
+ ctx->video_codec_id = ctx->video_codec_id ? ctx->video_codec_id
+ : AV_CODEC_ID_RAWVIDEO;
+
+ ranges->nb_components = (field->type == AV_OPT_TYPE_IMAGE_SIZE && (flags & AV_OPT_MULTI_COMPONENT_RANGE)) ? 3 : 1;
+ if (ctx->device_name[VideoDevice])
+ if ((ret = dshow_list_device_options(avctx, devenum, VideoDevice, VideoSourceDevice, ranges, query_type)) < 0)
+ goto fail2;
+ if (ctx->device_name[AudioDevice]) {
+ if (dshow_list_device_options(avctx, devenum, AudioDevice, AudioSourceDevice, ranges, query_type) < 0) {
+ /* show audio options from combined video+audio sources as fallback */
+ if ((ret = dshow_list_device_options(avctx, devenum, AudioDevice, VideoSourceDevice, ranges, query_type)) < 0)
+ goto fail2;
+ }
+ }
+ ret = ranges->nb_ranges ? ranges->nb_components : 0;
+
+ // when dealing with a multi-component item (regardless of whether
+ // AV_OPT_MULTI_COMPONENT_RANGE is set or not), we need to reorganize the
+ // output range array from [r1_c1 r1_c2 r1_c3 r2_c1 r2_c2 r2_c3 ...] to
+ // [r1_c1 r2_c1 ... r1_c2 r2_c2 ... r1_c3 r2_c3 ...] to be consistent with
+ // documentation of AVOptionRanges in libavutil/opt.h
+ if (ranges->nb_ranges && ranges->nb_components > 1) {
+ AVOptionRange **new_range = av_malloc_array(ranges->nb_components * ranges->nb_ranges, sizeof(*ranges->range));
+ AVOptionRange **old_range = ranges->range;
+ if (!new_range) {
+ ret = AVERROR(ENOMEM);
+ goto fail2;
+ }
+ ranges->nb_ranges /= ranges->nb_components;
+ for (int n = 0; n < ranges->nb_components * ranges->nb_ranges; n++) {
+ int i = n / ranges->nb_components;
+ int j = n % ranges->nb_components;
+ new_range[ranges->nb_ranges * j + i] = old_range[n];
+ }
+ ranges->range = new_range;
+ av_freep(&old_range);
+ }
+
+ // success, set output
+ *ranges_arg = ranges;
+
+fail2:
+ // set dshow parameters/options back to original values
+ // audio
+ ctx->sample_size = backup_sample_size;
+ ctx->sample_rate = backup_sample_rate;
+ ctx->channels = backup_channels;
+ // video
+ ctx->video_codec_id = backup_video_codec_id;
+ ctx->pixel_format = backup_pixel_format;
+ ctx->requested_width = backup_requested_width;
+ ctx->requested_height = backup_requested_height;
+ if (ctx->framerate)
+ av_free(ctx->framerate);
+ ctx->framerate = backup_framerate;
+
+ if (devenum)
+ ICreateDevEnum_Release(devenum);
+
+fail1:
+ if (ret < 0)
+ av_opt_freep_ranges(&ranges);
+
+ return ret;
+}
+
+// fake class to point av_opt_query_ranges to our query_ranges function
+static const AVClass dshow_dev_caps_class = {
+ .class_name = "",
+ .item_name = av_default_item_name,
+ .option = ff_device_capabilities,
+ .version = LIBAVUTIL_VERSION_INT,
+ .query_ranges = dshow_query_ranges,
+};
+
+static int dshow_create_device_capabilities(struct AVFormatContext *avctx, AVDeviceCapabilitiesQuery *caps)
+{
+ struct dshow_ctx *ctx = avctx->priv_data;
+ int ret = 0;
+ ICreateDevEnum *devenum = NULL;
+
+ // set class so queries work
+ caps->av_class = &dshow_dev_caps_class;
+
+ if (ctx->device_name[0] || ctx->device_name[1]) {
+ av_log(avctx, AV_LOG_ERROR, "You cannot query device capabilities on an opened device\n");
+ ret = AVERROR(EIO);
+ goto fail;
+ }
+
+ if (!parse_device_name(avctx)) {
+ av_log(avctx, AV_LOG_ERROR, "You must set a device name (AVFormatContext url) to specify which device to query capabilities from\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ CoInitialize(0);
+ if (CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ICreateDevEnum, (void **) &devenum)) {
+ av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
+ ret = AVERROR(EIO);
+ goto fail;
+ }
+
+ // check devices can be found
+ if (ctx->device_name[VideoDevice]) {
+ IBaseFilter *device_filter = NULL;
+ char *device_unique_name = NULL;
+ if ((ret = dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, &device_filter, &device_unique_name, NULL)) < 0)
+ return ret;
+
+ if (ret >= 0) {
+ ctx->device_filter[VideoDevice] = device_filter;
+ ctx->device_unique_name[VideoDevice] = device_unique_name;
+ }
+ }
+ if (ctx->device_name[AudioDevice]) {
+ IBaseFilter *device_filter = NULL;
+ char *device_unique_name = NULL;
+ if (dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, &device_filter, &device_unique_name, NULL) < 0) {
+ /* try to access audio from combined video+audio sources as fallback */
+ if ((ret = dshow_cycle_devices(avctx, devenum, AudioDevice, VideoSourceDevice, &device_filter, &device_unique_name, NULL)) < 0)
+ goto fail;
+ }
+ if (ret >= 0) {
+ ctx->device_filter[AudioDevice] = device_filter;
+ ctx->device_unique_name[AudioDevice] = device_unique_name;
+ }
+ }
+
+fail:
+ if (devenum)
+ ICreateDevEnum_Release(devenum);
+
+ if (ret < 0)
+ return ret;
+ else
+ return 0;
+}
+
+static int dshow_free_device_capabilities(struct AVFormatContext *avctx, AVDeviceCapabilitiesQuery *caps)
+{
+ // clear state variables that may have been set during the querying process
+ // (e.g. frees device names, removes device_filters, etc)
+ dshow_read_close(avctx);
+
+ return 0;
+}
+
#define OFFSET(x) offsetof(struct dshow_ctx, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
@@ -2059,6 +2449,8 @@ const AVInputFormat ff_dshow_demuxer = {
.read_close = dshow_read_close,
.get_device_list= dshow_get_device_list,
.control_message= dshow_control_message,
+ .create_device_capabilities = dshow_create_device_capabilities,
+ .free_device_capabilities = dshow_free_device_capabilities,
.flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK,
.priv_class = &dshow_class,
};
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 764aceccb5..5f8f371bea 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
#define LIBAVDEVICE_VERSION_MINOR 2
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
LIBAVDEVICE_VERSION_MINOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 17/21] avdevice/dshow: cosmetics
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (15 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 16/21] avdevice/dshow: implement capabilities API Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 18/21] avformat: add avformat_alloc_input_context() Diederick Niehorster
` (4 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 58476a0f40..3cae7d265e 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -933,6 +933,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
AVOptionRange *new_range[3] = { NULL };
int nb_range = 0;
struct dshow_format_info *fmt_info = NULL;
+
r = IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
if (r != S_OK)
goto next;
@@ -1558,7 +1559,8 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
goto error;
}
}
- if (ctx->device_filter[otherDevType]) {
+
+ if (ctx->device_filter[otherDevType]) {
// avoid adding add two instances of the same device to the graph, one for video, one for audio
// a few devices don't support this (could also do this check earlier to avoid double crossbars, etc. but they seem OK)
if (strcmp(device_filter_unique_name, ctx->device_unique_name[otherDevType]) == 0) {
@@ -2441,16 +2443,16 @@ static const AVClass dshow_class = {
};
const AVInputFormat ff_dshow_demuxer = {
- .name = "dshow",
- .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
- .priv_data_size = sizeof(struct dshow_ctx),
- .read_header = dshow_read_header,
- .read_packet = dshow_read_packet,
- .read_close = dshow_read_close,
- .get_device_list= dshow_get_device_list,
- .control_message= dshow_control_message,
+ .name = "dshow",
+ .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
+ .priv_data_size = sizeof(struct dshow_ctx),
+ .read_header = dshow_read_header,
+ .read_packet = dshow_read_packet,
+ .read_close = dshow_read_close,
+ .get_device_list = dshow_get_device_list,
+ .control_message = dshow_control_message,
.create_device_capabilities = dshow_create_device_capabilities,
- .free_device_capabilities = dshow_free_device_capabilities,
- .flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK,
- .priv_class = &dshow_class,
+ .free_device_capabilities = dshow_free_device_capabilities,
+ .flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK,
+ .priv_class = &dshow_class,
};
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 18/21] avformat: add avformat_alloc_input_context()
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (16 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 17/21] avdevice/dshow: cosmetics Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 19/21] doc/examples: adding device_get_capabilities example Diederick Niehorster
` (3 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
avformat_alloc_input_context function analogous to
avformat_alloc_output_context2, except that it does not take a filename
argument as guessing the format by just the filename does not make sense.
avformat_alloc_input_context can be used e.g. with the avdevice
capabilities API, which needs an allocated input format with priv_data
(and default options) set, but device should not be opened.
Added some checks to avformat_open_input, for the case that a
AVFormatContext* allocated by avformat_alloc_input_context is provided:
1. if avformat_open_input's AVInputFormat *fmt argument is not NULL,
clean up any already set s->iformat
2. if s->url is already set and avformat_open_input's filename argument
is not NULL, free current url and replace by provided filename
3. if s->url is already set and avformat_open_input's filename argument
is NULL, do not set s->url to "", but keep current url
4. if s->priv_data has already been allocated, do not do so again.
4b. do reset options to default and apply provided options (if any)
5. add 4b to docs of avformat_open_input
Bump libavformat version.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavformat/avformat.h | 29 +++++++++++++++--
libavformat/demux.c | 74 ++++++++++++++++++++++++++++++++++++++----
libavformat/version.h | 2 +-
3 files changed, 95 insertions(+), 10 deletions(-)
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 027a914e13..004d81640f 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -2024,6 +2024,26 @@ AVProgram *av_new_program(AVFormatContext *s, int id);
* @}
*/
+ /**
+ * Allocate an AVFormatContext for an input format.
+ * avformat_free_context() can be used to free the context and
+ * everything allocated by the framework within it. NB: in general
+ * the correct format cannot be known (unless the user has extra
+ * information) until the file is opened. If forcing a format by
+ * this method, but it turns out not to match the file's format
+ * upon avformat_open_input(), the latter will throw an error.
+ *
+ * @param *ctx is set to the created format context, or to NULL in
+ * case of failure
+ * @param iformat format to use for allocating the context, if NULL
+ * format_name is used instead
+ * @param format_name the name of input format to use for allocating the
+ * context
+ * @return >= 0 in case of success, a negative AVERROR code in case of
+ * failure
+ */
+int avformat_alloc_input_context(AVFormatContext **ctx, const AVInputFormat *iformat,
+ const char *format_name);
/**
* Allocate an AVFormatContext for an output format.
@@ -2119,9 +2139,9 @@ int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,
* Open an input stream and read the header. The codecs are not opened.
* The stream must be closed with avformat_close_input().
*
- * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
- * May be a pointer to NULL, in which case an AVFormatContext is allocated by this
- * function and written into ps.
+ * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context, or
+ * avformat_alloc_input_context). May be a pointer to NULL, in which case an
+ * AVFormatContext is allocated by this function and written into ps.
* Note that a user-supplied AVFormatContext will be freed on failure.
* @param url URL of the stream to open.
* @param fmt If non-NULL, this parameter forces a specific input format.
@@ -2129,6 +2149,9 @@ int av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,
* @param options A dictionary filled with AVFormatContext and demuxer-private options.
* On return this parameter will be destroyed and replaced with a dict containing
* options that were not found. May be NULL.
+ * Note that if a AVFormatContext allocated by avformat_alloc_input_context
+ * is provided, any demuxer-private options will be overwritten by their defaults
+ * before applying this new set of demuxer-private options, if any.
*
* @return 0 on success, a negative AVERROR on failure.
*
diff --git a/libavformat/demux.c b/libavformat/demux.c
index ef189d9d8e..52442b2e55 100644
--- a/libavformat/demux.c
+++ b/libavformat/demux.c
@@ -217,6 +217,56 @@ FF_ENABLE_DEPRECATION_WARNINGS
return 0;
}
+
+int avformat_alloc_input_context(AVFormatContext** avctx, const AVInputFormat* iformat,
+ const char* format)
+{
+ AVFormatContext* s = avformat_alloc_context();
+ int ret = 0;
+
+ *avctx = NULL;
+ if (!s)
+ goto nomem;
+
+ if (!iformat) {
+ if (format) {
+ iformat = av_find_input_format(format);
+ if (!iformat) {
+ av_log(s, AV_LOG_ERROR, "Requested input format '%s' not found\n", format);
+ ret = AVERROR(EINVAL);
+ goto error;
+ }
+ }
+ else {
+ av_log(s, AV_LOG_ERROR, "You should provide an input format or the name of an input format when calling this function\n");
+ ret = AVERROR(EINVAL);
+ goto error;
+ }
+ }
+
+ s->iformat = iformat;
+ if (s->iformat->priv_data_size > 0) {
+ s->priv_data = av_mallocz(s->iformat->priv_data_size);
+ if (!s->priv_data)
+ goto nomem;
+ if (s->iformat->priv_class) {
+ *(const AVClass**)s->priv_data = s->iformat->priv_class;
+ av_opt_set_defaults(s->priv_data);
+ }
+ }
+ else
+ s->priv_data = NULL;
+
+ *avctx = s;
+ return 0;
+nomem:
+ av_log(s, AV_LOG_ERROR, "Out of memory\n");
+ ret = AVERROR(ENOMEM);
+error:
+ avformat_free_context(s);
+ return ret;
+}
+
int avformat_open_input(AVFormatContext **ps, const char *filename,
const AVInputFormat *fmt, AVDictionary **options)
{
@@ -233,8 +283,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
av_log(NULL, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n");
return AVERROR(EINVAL);
}
- if (fmt)
+ if (fmt) {
+ if (s->iformat) {
+ if (s->iformat->priv_class && s->priv_data)
+ av_opt_free(s->priv_data);
+ av_freep(&s->priv_data);
+ }
s->iformat = fmt;
+ }
if (options)
av_dict_copy(&tmp, *options, 0);
@@ -245,7 +301,9 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
if ((ret = av_opt_set_dict(s, &tmp)) < 0)
goto fail;
- if (!(s->url = av_strdup(filename ? filename : ""))) {
+ if (filename && s->url)
+ av_freep(&s->url);
+ if (!s->url && !(s->url = av_strdup(filename ? filename : ""))) {
ret = AVERROR(ENOMEM);
goto fail;
}
@@ -288,12 +346,16 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
s->duration = s->start_time = AV_NOPTS_VALUE;
- /* Allocate private data. */
+ /* Allocate private data and set options. */
if (s->iformat->priv_data_size > 0) {
- if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
- ret = AVERROR(ENOMEM);
- goto fail;
+ /* allocate if not already allocated */
+ if (!s->priv_data) {
+ if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
}
+ /* Overwrite any options already set (1: back to defaults, 2: apply options, if any) */
if (s->iformat->priv_class) {
*(const AVClass **) s->priv_data = s->iformat->priv_class;
av_opt_set_defaults(s->priv_data);
diff --git a/libavformat/version.h b/libavformat/version.h
index 88d6f750a2..4a7d2f441c 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
#include "version_major.h"
-#define LIBAVFORMAT_VERSION_MINOR 23
+#define LIBAVFORMAT_VERSION_MINOR 24
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 19/21] doc/examples: adding device_get_capabilities example
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (17 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 18/21] avformat: add avformat_alloc_input_context() Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 20/21] Makefile/examples: cosmetics Diederick Niehorster
` (2 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
This example also shows use of get_device_list API.
Also improve capability API doc in avdevice.h: now point to this example
instead of rough example code given in the header.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
configure | 2 +
doc/examples/.gitignore | 1 +
doc/examples/Makefile | 1 +
doc/examples/Makefile.example | 1 +
doc/examples/device_get_capabilities.c | 243 +++++++++++++++++++++++++
libavdevice/avdevice.h | 33 +---
6 files changed, 249 insertions(+), 32 deletions(-)
create mode 100644 doc/examples/device_get_capabilities.c
diff --git a/configure b/configure
index e4d36aa639..be78a2119e 100755
--- a/configure
+++ b/configure
@@ -1726,6 +1726,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
@@ -3751,6 +3752,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..de707bb3ca 100644
--- a/doc/examples/Makefile
+++ b/doc/examples/Makefile
@@ -3,6 +3,7 @@ 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
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..1cfbca64eb
--- /dev/null
+++ b/doc/examples/device_get_capabilities.c
@@ -0,0 +1,243 @@
+/*
+ * 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 <libavformat/avformat.h>
+#include <libavdevice/avdevice.h>
+#include <libavutil/avstring.h>
+#include <libavutil/log.h>
+#include <libavutil/bprint.h>
+
+static int print_option_ranges(enum AVOptionType type, AVOptionRanges *ranges)
+{
+ for (int range_index = 0; range_index < ranges->nb_ranges; range_index++) {
+ int ret;
+ char *out_val = NULL;
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ 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)
+ av_bprintf(&bp, ", ");
+ av_bprintf(&bp, "%s: ", range->str);
+ if (range->value_min > range->value_max)
+ av_bprintf(&bp, "<value not available>");
+ else {
+ avdevice_capabilities_bprint_num(&bp, range->str, range->value_min);
+ if (range->is_range) {
+ av_bprintf(&bp, " -- ");
+ avdevice_capabilities_bprint_num(&bp, range->str, range->value_max);
+ }
+ }
+ }
+ if (!av_bprint_is_complete(&bp))
+ return AVERROR(ENOMEM);
+ if ((ret = av_bprint_finalize(&bp, &out_val)) < 0)
+ return ret;
+ printf("%s\n", out_val);
+ av_freep(&out_val);
+ }
+
+ return 0;
+}
+
+static void list_queries(void)
+{
+ const AVOption *opt = NULL;
+ const AVClass *class = avdevice_capabilities_get_class();
+ while (opt = av_opt_next(&class, opt))
+ fprintf(stderr, " %s\n", opt->name);
+}
+
+static void list_device_sources(const AVInputFormat *fmt)
+{
+ int ret;
+ AVDeviceInfoList *device_list = NULL;
+
+ if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category))
+ return;
+
+ if (!fmt->get_device_list) {
+ ret = AVERROR(ENOSYS);
+ fprintf(stderr, " Cannot list sources. Not implemented.\n");
+ return;
+ }
+
+ if ((ret = avdevice_list_input_sources(fmt, NULL, NULL, &device_list)) < 0) {
+ fprintf(stderr, " Cannot list sources.\n");
+ return;
+ }
+
+ for (int i = 0; i < device_list->nb_devices; i++) {
+ const AVDeviceInfo *device = device_list->devices[i];
+ fprintf(stderr, " %s %s (", device_list->default_device == i ? "*" : " ", device->device_name);
+ if (device->nb_media_types > 0 && device->media_types) {
+ for (int j = 0; j < device->nb_media_types; ++j) {
+ const char* media_type = av_get_media_type_string(device->media_types[j]);
+ if (j > 0)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "%s", media_type ? media_type : "unknown");
+ }
+ }
+ else {
+ fprintf(stderr, "none");
+ }
+ fprintf(stderr, ")\n");
+ }
+
+ avdevice_free_list_devices(&device_list);
+}
+
+
+
+int main (int argc, char **argv)
+{
+ int ret = 0;
+ const char *device_name = NULL;
+ const char *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;
+ const AVOption *opt = NULL;
+
+ if (argc != 6) {
+ fprintf(stderr, "usage: %s device_name 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 dshow video=\"Integrated Webcam\" frame_size pixel_format yuyv422",
+ argv[0], argv[0]);
+ exit(1);
+ }
+ device_name = argv[1];
+ input_name = argv[2];
+ query_cap = argv[3];
+ set_cap_name = argv[4];
+ set_cap_value = argv[5];
+
+ // make sure avdevices can be found among input and output formats
+ avdevice_register_all();
+ // find specified device
+ fmt = av_find_input_format(device_name);
+ if (!fmt) {
+ fprintf(stderr, "Could not find the device '%s'\n",device_name);
+ ret = AVERROR(EINVAL);
+ goto end;
+ }
+
+ // prepare device format context, and set device to query,
+ ret = avformat_alloc_input_context(&fmt_ctx, fmt, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "Cannot allocate input format context\n");
+ goto end;
+ }
+ fmt_ctx->url = av_strdup(input_name);
+
+ // prepare query object, setting device options
+ ret = avdevice_capabilities_create(&caps, fmt_ctx, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "avdevice_capabilities_create() failed. Possibly the input name you specified ('%s') is not available for this device ('%s').\n%s can access the following sources:\n", input_name, device_name, device_name);
+ list_device_sources(fmt);
+ goto end;
+ }
+
+ // check capability to query, and get info about the return type
+ opt = av_opt_find(caps, query_cap, NULL, 0, 0);
+ if (!opt) {
+ fprintf(stderr, "Capability '%s' you wish to query is not available.\nYou can query the following capabilities:\n", query_cap);
+ list_queries();
+ ret = AVERROR_OPTION_NOT_FOUND;
+ goto end;
+ }
+
+ // query the capability without any filter set
+ ret = av_opt_query_ranges(&ranges, caps, opt->name, AV_OPT_MULTI_COMPONENT_RANGE);
+ if (ret < 0) {
+ fprintf(stderr, "av_opt_query_ranges() failed\n");
+ goto end;
+ }
+
+ // print results
+ ret = print_option_ranges(opt->type, ranges);
+ if (ret < 0) {
+ fprintf(stderr, "printing the AVOptionRanges failed\n");
+ goto end;
+ }
+ 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) {
+ fprintf(stderr, "av_opt_set() failed when trying to set the capability '%s'. Possibly it is not available.\nYou can set the following capabilities:\n", set_cap_name);
+ list_queries();
+ goto end;
+ }
+
+ // query again
+ ret = av_opt_query_ranges(&ranges, caps, opt->name, AV_OPT_MULTI_COMPONENT_RANGE);
+ if (ret < 0) {
+ fprintf(stderr, "av_opt_query_ranges() failed\n");
+ goto end;
+ }
+
+ // print results
+ print_option_ranges(opt->type, ranges);
+
+
+end:
+ if (ranges)
+ av_opt_freep_ranges(&ranges);
+ if (caps)
+ avdevice_capabilities_free(&caps, fmt_ctx);
+
+ if (fmt_ctx)
+ avformat_free_context(fmt_ctx);
+
+ 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;
+}
diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h
index 5f9dfccc34..c29d8940a5 100644
--- a/libavdevice/avdevice.h
+++ b/libavdevice/avdevice.h
@@ -384,38 +384,7 @@ int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
* For example, setting a codec may impact number of formats or fps values
* returned during next query. Setting invalid value may limit results to zero.
*
- * Example of the usage basing on opengl output device:
- *
- * @code
- * AVFormatContext *oc = NULL;
- * AVDeviceCapabilitiesQuery *caps = NULL;
- * AVOptionRanges *ranges;
- * int ret;
- *
- * if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0)
- * goto fail;
- * if (avdevice_capabilities_create(&caps, oc, NULL) < 0)
- * goto fail;
- *
- * //query codecs
- * if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
- * goto fail;
- * //pick codec here and set it
- * av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0);
- *
- * //query format
- * if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
- * goto fail;
- * //pick format here and set it
- * av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0);
- *
- * //query and set more capabilities
- *
- * fail:
- * //clean up code
- * avdevice_capabilities_free(&query, oc);
- * avformat_free_context(oc);
- * @endcode
+ * @see examples/device_get_capabilities.c
*/
typedef struct AVDeviceCapabilitiesQuery AVDeviceCapabilitiesQuery;
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 20/21] Makefile/examples: cosmetics
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (18 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 19/21] doc/examples: adding device_get_capabilities example Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 21/21] avdevice/dshow: capabilities query also works on opened device Diederick Niehorster
2022-04-25 20:23 ` [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick C. Niehorster
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
doc/examples/Makefile | 48 +++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/doc/examples/Makefile b/doc/examples/Makefile
index de707bb3ca..7988ed4226 100644
--- a/doc/examples/Makefile
+++ b/doc/examples/Makefile
@@ -1,27 +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_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
+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
EXAMPLES := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF))
EXAMPLES_G := $(EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)_g$(EXESUF))
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH v5 21/21] avdevice/dshow: capabilities query also works on opened device
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (19 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 20/21] Makefile/examples: cosmetics Diederick Niehorster
@ 2022-03-30 12:18 ` Diederick Niehorster
2022-04-25 20:23 ` [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick C. Niehorster
21 siblings, 0 replies; 26+ messages in thread
From: Diederick Niehorster @ 2022-03-30 12:18 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Diederick Niehorster
While the capabilities API is in principle meant to be used with an
allocated format context belonging to an unopened device, small changes
make it work for an opened dshow device as well. So hereby done.
Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
---
libavdevice/dshow.c | 110 +++++++++++++++++++++---------------
libavdevice/dshow_capture.h | 3 +
2 files changed, 66 insertions(+), 47 deletions(-)
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 3cae7d265e..1e4025983a 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -849,7 +849,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
void *caps = NULL;
int i, n, size, r;
int wait_for_better = 0;
- int use_default;
+ int use_default, already_opened;
// format parameters requested by user
// if none are requested by user, the values will below be set to
@@ -875,6 +875,9 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
if (!caps)
goto end;
+ // get if device is already opened
+ already_opened = ctx->device_name[0] || ctx->device_name[1];
+
/**
* If we should open the device with the default format,
* then:
@@ -1153,7 +1156,7 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
// in ranges, try to apply in all cases, and store
// caps if successfully applied
if (!wait_for_better || ranges) {
- if (IAMStreamConfig_SetFormat(config, type) != S_OK)
+ if (!already_opened && IAMStreamConfig_SetFormat(config, type) != S_OK) // skip if device already opened
goto next;
else if (ranges) {
// format matched and could be set successfully.
@@ -1494,12 +1497,19 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
char *device_unique_name = NULL;
int r;
- if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name, NULL)) < 0)
- return r;
- ctx->device_filter[devtype] = device_filter;
- ctx->device_unique_name[devtype] = device_unique_name;
+ if (!ctx->device_filter[devtype]) {
+ if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name, NULL)) < 0)
+ return r;
+
+ // put them in context so they'll be cleaned up again
+ ctx->device_filter[devtype] = device_filter;
+ ctx->device_unique_name[devtype] = device_unique_name;
+ } else
+ device_filter = ctx->device_filter[devtype];
+
if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, ranges ? &device_pin : NULL, ranges, query_type)) < 0)
return r;
+
return 0;
}
@@ -2319,7 +2329,8 @@ fail1:
return ret;
}
-// fake class to point av_opt_query_ranges to our query_ranges function
+// fake class to point av_opt functions to capabilities that can be queried,
+// and av_opt_query_ranges to our query_ranges function
static const AVClass dshow_dev_caps_class = {
.class_name = "",
.item_name = av_default_item_name,
@@ -2337,49 +2348,51 @@ static int dshow_create_device_capabilities(struct AVFormatContext *avctx, AVDev
// set class so queries work
caps->av_class = &dshow_dev_caps_class;
- if (ctx->device_name[0] || ctx->device_name[1]) {
- av_log(avctx, AV_LOG_ERROR, "You cannot query device capabilities on an opened device\n");
- ret = AVERROR(EIO);
- goto fail;
- }
+ // check if device setup is needed or we will be querying capabilities of an already opened device
+ ctx->cap_query_already_opened = ctx->device_name[0] || ctx->device_name[1];
+ if (ctx->cap_query_already_opened)
+ av_log(avctx, AV_LOG_WARNING, "Querying device capabilities on an opened device: may yield false positives\n");
- if (!parse_device_name(avctx)) {
- av_log(avctx, AV_LOG_ERROR, "You must set a device name (AVFormatContext url) to specify which device to query capabilities from\n");
- ret = AVERROR(EINVAL);
- goto fail;
- }
-
- CoInitialize(0);
- if (CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
- &IID_ICreateDevEnum, (void **) &devenum)) {
- av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
- ret = AVERROR(EIO);
- goto fail;
- }
+ // if device not already opened, check that what user specified can be opened
+ if (!ctx->cap_query_already_opened) {
+ if (!parse_device_name(avctx)) {
+ av_log(avctx, AV_LOG_ERROR, "You must set a device name (AVFormatContext url) to specify which device to query capabilities from\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
- // check devices can be found
- if (ctx->device_name[VideoDevice]) {
- IBaseFilter *device_filter = NULL;
- char *device_unique_name = NULL;
- if ((ret = dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, &device_filter, &device_unique_name, NULL)) < 0)
- return ret;
-
- if (ret >= 0) {
- ctx->device_filter[VideoDevice] = device_filter;
- ctx->device_unique_name[VideoDevice] = device_unique_name;
+ CoInitialize(0);
+ if (CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ICreateDevEnum, (void **) &devenum)) {
+ av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
+ ret = AVERROR(EIO);
+ goto fail;
}
- }
- if (ctx->device_name[AudioDevice]) {
- IBaseFilter *device_filter = NULL;
- char *device_unique_name = NULL;
- if (dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, &device_filter, &device_unique_name, NULL) < 0) {
- /* try to access audio from combined video+audio sources as fallback */
- if ((ret = dshow_cycle_devices(avctx, devenum, AudioDevice, VideoSourceDevice, &device_filter, &device_unique_name, NULL)) < 0)
- goto fail;
+
+ // check devices can be found
+ if (ctx->device_name[VideoDevice]) {
+ IBaseFilter *device_filter = NULL;
+ char *device_unique_name = NULL;
+ if ((ret = dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, &device_filter, &device_unique_name, NULL)) < 0)
+ return ret;
+
+ if (ret >= 0) {
+ ctx->device_filter[VideoDevice] = device_filter;
+ ctx->device_unique_name[VideoDevice] = device_unique_name;
+ }
}
- if (ret >= 0) {
- ctx->device_filter[AudioDevice] = device_filter;
- ctx->device_unique_name[AudioDevice] = device_unique_name;
+ if (ctx->device_name[AudioDevice]) {
+ IBaseFilter *device_filter = NULL;
+ char *device_unique_name = NULL;
+ if (dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, &device_filter, &device_unique_name, NULL) < 0) {
+ /* try to access audio from combined video+audio sources as fallback */
+ if ((ret = dshow_cycle_devices(avctx, devenum, AudioDevice, VideoSourceDevice, &device_filter, &device_unique_name, NULL)) < 0)
+ goto fail;
+ }
+ if (ret >= 0) {
+ ctx->device_filter[AudioDevice] = device_filter;
+ ctx->device_unique_name[AudioDevice] = device_unique_name;
+ }
}
}
@@ -2395,9 +2408,12 @@ fail:
static int dshow_free_device_capabilities(struct AVFormatContext *avctx, AVDeviceCapabilitiesQuery *caps)
{
+ struct dshow_ctx *ctx = avctx->priv_data;
+
// clear state variables that may have been set during the querying process
// (e.g. frees device names, removes device_filters, etc)
- dshow_read_close(avctx);
+ if (!ctx->cap_query_already_opened)
+ dshow_read_close(avctx);
return 0;
}
diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h
index 94ba9896b7..a2c107b19c 100644
--- a/libavdevice/dshow_capture.h
+++ b/libavdevice/dshow_capture.h
@@ -345,6 +345,9 @@ struct dshow_ctx {
int sample_rate;
int sample_size;
int channels;
+
+ // for capabilities query
+ int cap_query_already_opened;
};
/*****************************************************************************
--
2.28.0.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements
2022-03-30 12:17 [FFmpeg-devel] [PATCH v5 00/21] avdevice (mostly dshow) enhancements Diederick Niehorster
` (20 preceding siblings ...)
2022-03-30 12:18 ` [FFmpeg-devel] [PATCH v5 21/21] avdevice/dshow: capabilities query also works on opened device Diederick Niehorster
@ 2022-04-25 20:23 ` Diederick C. Niehorster
21 siblings, 0 replies; 26+ messages in thread
From: Diederick C. Niehorster @ 2022-04-25 20:23 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Ping for the series, especially the first commit in the series which
should spark some discussion.
Thanks!
Dee
On Wed, Mar 30, 2022 at 2:18 PM Diederick Niehorster <dcnieho@gmail.com> wrote:
>
> This patch series implements a series of features, mostly enhancing the
> dshow avdevice, but also adding new functionality to avformat.
> This whole patchset enabled users of the FFmpeg API to fully
> query and control a dshow device, making FFmpeg a nice backend for any
> program that needs access to, e.g., a webcam.
>
> Different from v3 and v4, part of the patches has now been accepted, so
> only remaining features are in this set. Importantly, as per discussion
> on the list (
> https://ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281513.html, see
> especially https://ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281586.html),
> to resolve the the unholy ABI-relationship between libavdevice and
> libavformat and allow easier working on the part of the avdevice API
> that lives in avformat, avdevice is now locked to a specific major and minor
> version of avformat. This is documented in libavdevice/avdevice.h.
>
> Regarding new functionality added to avformat:
> Querying the capabilities of a dshow device is also possible on a
> device that is already opened. I expect/guess however that it may not be
> possible to achieve that for all of the avdevices, so in principle it is
> important that this patchset adds the ability to create an allocated but
> unopened AVFormatContext+AVInputFormat with the new function
> avformat_alloc_input_context(). This is tested in the new
> device_get_capabilities example.
>
> Diederick Niehorster (21):
> avdevice: lock to minor version of avformat
> avformat: add control_message function to AVInputFormat
> avdevice/dshow: implement control_message interface
> avdevice: add control message requesting to show config dialog
> avdevice/dshow: accept show config dialog control message
> avdevice/dshow: add config dialog command for crossbar and tv tuner
> avdevice/avdevice: Revert "Deprecate AVDevice Capabilities API"
> avdevice/avdevice: clean up avdevice_capabilities_create
> avdevice: capabilities API details no longer public
> avutil/opt: document AVOptionRange min_value > max_value
> avdevice: Add internal helpers for querying device capabilities
> avdevice: change device capabilities option type
> avdevice: improve capabilities' option API
> avdevice/dshow: move audio format helpers
> avdevice/dshow: when closing, set context fields back to zero
> avdevice/dshow: implement capabilities API
> avdevice/dshow: cosmetics
> avformat: add avformat_alloc_input_context()
> doc/examples: adding device_get_capabilities example
> Makefile/examples: cosmetics
> avdevice/dshow: capabilities query also works on opened device
>
> configure | 2 +
> doc/examples/.gitignore | 1 +
> doc/examples/Makefile | 47 +-
> doc/examples/Makefile.example | 1 +
> doc/examples/device_get_capabilities.c | 243 ++++++++++
> doc/indevs.texi | 34 ++
> libavdevice/avdevice.c | 177 ++++++-
> libavdevice/avdevice.h | 111 ++---
> libavdevice/dshow.c | 641 +++++++++++++++++++++++--
> libavdevice/dshow_capture.h | 14 +
> libavdevice/dshow_crossbar.c | 91 ++--
> libavdevice/internal.h | 66 +++
> libavdevice/utils.c | 48 ++
> libavdevice/version.h | 15 +-
> libavdevice/version_major.h | 2 +-
> libavformat/avformat.h | 59 ++-
> libavformat/demux.c | 74 ++-
> libavformat/utils.c | 5 +
> libavformat/version.h | 14 +-
> libavutil/avutil.h | 3 +
> libavutil/macros.h | 3 +
> libavutil/opt.c | 2 +-
> libavutil/opt.h | 5 +
> 23 files changed, 1462 insertions(+), 196 deletions(-)
> create mode 100644 doc/examples/device_get_capabilities.c
>
> --
> 2.28.0.windows.1
>
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread