diff mbox series

[FFmpeg-devel,v5,03/21] avdevice/dshow: implement control_message interface

Message ID 20220330121806.822-4-dcnieho@gmail.com
State New
Headers show
Series avdevice (mostly dshow) enhancements | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished

Commit Message

Diederick C. Niehorster March 30, 2022, 12:17 p.m. UTC
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 mbox series

Patch

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, \