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.

Signed-off-by: Diederick Niehorster <dcni...@gmail.com>
---
 libavdevice/dshow.c         | 42 +++++++++++++++++++++++++++++++++++++
 libavdevice/dshow_capture.h |  1 +
 2 files changed, 43 insertions(+)

diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index 3e41f4f99f..9f041e90f8 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -1079,6 +1079,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) {
@@ -1317,6 +1356,7 @@ static int dshow_read_header(AVFormatContext *avctx)
             }
         }
     }
+    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) {
@@ -1390,6 +1430,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;
 
@@ -1502,6 +1543,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 5a2691518c..bb0f76a8f2 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;
-- 
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-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to