diff mbox series

[FFmpeg-devel,v2,33/33] avdevice/dshow: capabilities query also works on opened device

Message ID 20210611203104.1692-34-dcnieho@gmail.com
State Superseded, archived
Headers show
Series avdevice (mostly dshow) enhancements
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Diederick C. Niehorster June 11, 2021, 8:31 p.m. UTC
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 | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index d3937df41a..11fa71db13 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -853,7 +853,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
@@ -879,6 +879,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:
@@ -1187,7 +1190,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.
@@ -1513,12 +1516,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;
+    } 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;
+
+    if (!ctx->device_filter[devtype]) {
+        // 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;
+    }
     return 0;
 }
 
@@ -2188,6 +2198,7 @@  static int dshow_query_ranges(AVOptionRanges** ranges_arg, void* obj, const char
     AVDeviceCapabilitiesQuery *caps = obj;
     const AVFormatContext *avctx = caps->device_context;
     struct dshow_ctx *ctx = avctx->priv_data;
+    int already_opened;
 
     int backup_sample_size;
     int backup_sample_rate;
@@ -2227,13 +2238,11 @@  static int dshow_query_ranges(AVOptionRanges** ranges_arg, void* obj, const char
         goto fail1;
     }
 
-    if (ctx->device_name[0]) {
-        av_log(avctx, AV_LOG_ERROR, "You cannot query device capabilities on an opened device\n");
-        ret = AVERROR(EIO);
-        goto fail1;
-    }
+    already_opened = ctx->device_name[0] || ctx->device_name[1];
+    if (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)) {
+    if (!already_opened && !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 fail1;
@@ -2349,7 +2358,8 @@  fail2:
 
     // clear state variables that may have been set during the above process
     // (e.g. frees device names, removes device_filters, etc)
-    dshow_read_close(avctx);
+    if (!already_opened)
+        dshow_read_close(avctx);
 
 fail1:
     if (ret < 0)