DirectShow IMediaControl возвращает неправильнные коды

Как вы уже знаете, я переписываю на C# свой старый видеоплеер. Он работает по такому принципу:
Form > Player GUI > Player engine
То есть, на форме лежит UserControl, который использует движок плеера, в котором прописаны интерфейсы DirectShow.
код движка:

        public int Play()
        {
            int res = S_OK;
            if (State == PLAYER_STATE.Null)
            {
                res = BuildGraph();
            }
            if (State != PLAYER_STATE.Null)
            {
                _state = PLAYER_STATE.Playing;
                mediaControl.Run(); //тут всегда S_FALSE. Это глюк WinAPI.
                return S_OK;
            }
            return res;
        }
        
        public int Pause()
        {
            System.Diagnostics.Debug.WriteLine($"Engine before pause: {State}");
            int res = State == PLAYER_STATE.Null ? S_FALSE : mediaControl.Pause();
            if (res == S_OK)
            {
                _state = PLAYER_STATE.Paused;
            }
            System.Diagnostics.Debug.WriteLine($"Engine after pause: {State}");
            return res;
        }

Код GUI (UserControl):

        private ZeratoolPlayerEngine playerEngine;
        public PLAYER_STATE State => playerEngine.State;




        public int Play()
        {
            if (State == PLAYER_STATE.Null)
            {
                playerEngine.GraphMode = PrefferedGraphMode;
            }

            int res = playerEngine.Play();

            btnPlay.BackgroundImage = res == S_OK ? Resources.play_active.ToBitmap() : Resources.play_inactive;
            btnPause.BackgroundImage = Resources.pause_inactive;

            return res;
        }

        public int Pause()
        {
            System.Diagnostics.Debug.WriteLine($"GUI before pause: {State}");
            if (State == PLAYER_STATE.Paused)
            {
                return S_FALSE;
            }
            int res = playerEngine.Pause();
            System.Diagnostics.Debug.WriteLine($"GUI Pause result: {ZeratoolPlayerEngine.ErrorCodeToString(res)}");
            System.Diagnostics.Debug.WriteLine($"GUI after pause: {State}");
            if (res == S_OK)
            {
                btnPlay.BackgroundImage = Resources.play_inactive;
                btnPause.BackgroundImage = Resources.pause_active.ToBitmap();

                seekBar.Refresh();
                UpdateTrackPositionIndicator();
            }
            return res;
        }

код формы:

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine(e.KeyCode);
            int errorCode;
            if (activePlayer != null)
            {
                switch (e.KeyCode)
                {
                    case Keys.Escape:
                    case Keys.Enter:
                        Close();
                        return;

                    case Keys.Space:
                        System.Diagnostics.Debug.WriteLine($"\nPressed space: {activePlayer.State}");
                        errorCode = PlayerPlayPause(activePlayer);
                        /*if (errorCode != S_OK)
                        {
                            ShowError(errorCode);
                        }*/
                        break;

                    case Keys.R:
                        System.Diagnostics.Debug.WriteLine("\nRebuild key pressed");
                        double pos = activePlayer.TrackPosition;
                        activePlayer.Clear();
                        if (activePlayer.Play() == S_OK && pos > 0.0)
                        {
                            activePlayer.TrackPosition = pos;
                        }
                        System.Diagnostics.Debug.WriteLine($"State after rebuild: {activePlayer.State}");
                        break;
                }
            }
        }

        private int PlayerPlayPause(ZeratoolPlayerGui pl)
        {
            switch (pl.State)
            {
                case PLAYER_STATE.Null:
                    return pl.Play();
                
                case PLAYER_STATE.Paused:
                case PLAYER_STATE.Stopped:
                    return pl.Play();

                case PLAYER_STATE.Playing:
                    return pl.Pause();

                default:
                    return S_OK;
            }
        }

Когда нажимаем на R, то плеер останавливается, очищается, перестраивает Граф, и приобретает состояние Stopped. То есть, когда Граф построен без ошибок, но еще не запущен. После этого, он сразу запускается, возвращается на позицию, где был остановлен и приобретает состояние Playing.
Проблема в том, что если нажать R и, не дожидаясь перестройки графа, нажать Пробел, то IMediaControl.Pause() вернёт S_FALSE и состояние плеера останется равным Playing. Хотя реально пауза сработает. В результате получается рассинхрон состояний. Видео стоит на паузе, а плеер находится в режиме Playing.
Выхлоп консоли, когда нажали R+Пробел при уже запущеном видео:


Rebuild key pressed
State after rebuild: Playing

Pressed space: Playing
GUI before pause: Playing
Engine before pause: Playing
Engine after pause: Playing
GUI Pause result: S_FALSE
GUI after pause: Playing

Я так понимаю, это не у меня в коде косяк? :thinking:
Переписал с игнорированием кодов возврата. Так работает, но вся логика сломалась.

Так мсдн же говорит, что это норм.

If method returns S_FALSE , it means that the method returned before all of the filters switched to a running state. The filters will complete the transition after the method returns. Optionally, you can wait for the transition to complete by calling the IMediaControl::GetState method with a timeout value. However, this is not required.

А под running stateом что имеется?
Как фильтры могут быть не готовы, если, по факту всё работает, даже при возвращённом S_FALSE? :thinking:
Run() вообще всегда возвращает s_false. Даже если построить Граф, но запускать его не сразу, а делать это по кнопке после долгого ожидания.

Видимо асинхронность какая-то используется и Run не ждет завершения всех процессов.