Поделиться через


Поток данных в DVD-навигаторе

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

DVD-навигатор имеет методы для остановки и приостановки воспроизведения. Эти методы похожи на методы Stop и Pause в IMediaControl, но не идентичны. Вот разница между ними:

  • Методы IDvdControl2 изменяют то, что DVD-навигатор считывает с диска. Они не изменяют состояние графа.
  • Методы IMediaControl изменяют состояние графа. Они не изменяют то, что DVD-навигатор считывает с диска. (Существует одно важное исключение, описанное в следующем разделе, связанное с методом Stop .)

Например, метод IDvdControl2::P ause выдает команду "Pause_On" приложения J, но не приостанавливает работу фильтра. С другой стороны, метод IMediaControl::P ause приостанавливает работу графа, но не выдает никаких команд DVD.

Как правило, вместо соответствующих методов IDvdControl2 используйте методы IMediaControl::P ause и Stop. Методы IMediaControl имеют очень небольшие задержки, тогда как методы IDvdControl2 могут иметь задержку до двух секунд.

Остановка воспроизведения

Поведение IMediaControl::Stop зависит от флага, который можно задать с помощью метода IDvdControl2::SetOption .

  • Если флаг DVD_ResetOnStop имеет значение FALSE, IMediaControl::Stop останавливает граф, но не изменяет домен DVD-навигатора. При повторном вызове run воспроизведение возобновляется из текущей позиции.
  • Если DVD_ResetOnStop имеет значение TRUE, IMediaControl::Stop приведет к сбросу DVD-навигатора. При повторном вызове IMediaControl::Run DVD-навигатор воспроизводится из домена First Play, как если бы вы вставляли DVD-диск в первый раз.

Флаг DVD_ResetOnStop по умолчанию имеет значение TRUE для совместимости со старыми приложениями. Однако обычно следует переопределить значение по умолчанию и установить для флага значение FALSE. Причина в том, что некоторые события могут привести к остановке графа во время воспроизведения. Например, при изменении разрешения экрана граф фильтра останавливается, повторно подключает отрисовщик видео и перезапускается. Если DVD_ResetOnStop имеет значение TRUE, воспроизведение будет перезапущено с начала диска. Вероятно, это не то, что ожидает пользователь.

Таким образом, в начале приложения вызовите SetOption с DVD_ResetOnStop значением FALSE. Если вы хотите остановить воспроизведение и возобновить его из того же расположения, вызовите IMediaControl::Stop или IMediaControl::P ause. Если вы хотите остановить воспроизведение и сбросить диск, вызовите Метод SetOption с DVD_ResetOnStop, равным TRUE; затем вызовите IMediaControl::Stop; наконец, снова вызовите SetOption и сбросьте DVD_ResetOnStop на FALSE.

Приостановка воспроизведения

Если вы предоставите DVD-навигатору команду во время приостановки графа, команда может не завершиться до повторного запуска графа. В некоторых ситуациях это может привести к взаимоблокировке в приложении. Существует два правила, которые следует соблюдать, чтобы избежать взаимоблокировок:

  • Во время приостановки не следует выполнять более одной асинхронной команды DVD.
  • Во время приостановки не блокируйте поток пользовательского интерфейса приложения или поток, изменяющий состояние графа.

Второе правило стоит изучить более подробно. Ниже приведены некоторые сценарии, которые могут вызвать взаимоблокировку.

  • Сценарий. Во время приостановки приложение выдает команду DVD с флагом блокировки. Это может привести к взаимоблокировке, если поток, который выдает команду DVD, является тем же потоком, который выдает команду run. Команда DVD-диска блокируется до тех пор, пока граф не запустится, но граф не может выполняться до завершения команды.

    Рекомендация. Выполните команду DVD в отдельном рабочем потоке или не используйте флаг блокировки.

  • Сценарий. Во время приостановки приложение выполняет команду DVD, а затем вызывает IDvdCmd::WaitForEnd для объекта команды. Эта ситуация эквивалентна предыдущему примеру. При вызове метода Wait из потока пользовательского интерфейса поток пользовательского интерфейса не сможет запустить граф, пока не разблокирует метод Wait , но метод Wait не разблокирует его до запуска графа.

    Рекомендация. Вызов ожидания в рабочем потоке.

  • Сценарий. Во время работы графа приложение выдает команду DVD с флагом блокировки, а затем вызывает pause из другого потока. Это возможное состояние гонки, так как граф может приостановиться перед выполнением команды. Если один из двух потоков является потоком пользовательского интерфейса, вы можете вызвать взаимоблокировку, аналогичную двум предыдущим примерам. В этом примере показана важность написания потокобезопасного кода, если приложение использует несколько потоков.

    Рекомендация. Если вы используете рабочие потоки, убедитесь, что код является потокобезопаснным.

  • Сценарий. При приостановке приложение отключает команду выполнения в пользовательском интерфейсе, а затем выдает асинхронную команду DVD. Этот случай не является строго взаимоблокировкой, так как поток приложения по-прежнему выполняется. Однако теперь пользователю не удается запустить граф, поэтому команда никогда не будет выполнена.

    Рекомендация. При приостановке всегда оставляйте команду выполнения включенной.

Поиск DVD-диска в указанное время

Чтобы точно найти указанное время на диске, вызовите IMediaControl::Run. Затем вызовите IDvdControl2::P layAtTime, указав время и задав параметру dwFlags значение DVD_CMD_FLAG_Flush.

Dvd-приложения