Compartilhar via


Fluxo de Dados no Navegador de DVD

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

O Navegador de DVD tem métodos para interromper e pausar a reprodução. Esses métodos são semelhantes — mas não idênticos — aos métodos Stop e Pause no IMediaControl. Aqui está a diferença entre eles:

  • Os métodos IDvdControl2 alteram o que o Navegador de DVD lê do disco. Eles não alteram o estado do grafo.
  • Os métodos IMediaControl alteram o estado do grafo. Eles não alteram o que o Navegador de DVD lê do disco. (Há uma exceção importante, explicada na próxima seção, relacionada ao método Stop .)

Por exemplo, o método IDvdControl2::P ause emite o comando "Pause_On" Anexo J, mas não pausa o grafo de filtro. O método IMediaControl::P ause , por outro lado, pausa o grafo, mas não emite nenhum comando de DVD.

Em geral, use os métodos IMediaControl::P ause e Stop em vez dos métodos IDvdControl2 correspondentes. Os métodos IMediaControl têm latências muito pequenas, enquanto os métodos IDvdControl2 podem ter até dois segundos de latência.

Interrompendo a reprodução

O comportamento de IMediaControl::Stop depende de um sinalizador que você pode definir com o método IDvdControl2::SetOption .

  • Se o sinalizador DVD_ResetOnStop for FALSE, IMediaControl::Stop interromperá o grafo, mas não alterará o domínio do Navegador de DVD. Quando você chama executar novamente, a reprodução é retomada da posição atual.
  • Se DVD_ResetOnStop for TRUE, IMediaControl::Stop fará com que o Navegador de DVD seja redefinido. Quando você chama IMediaControl::Run novamente, o Navegador de DVD é reproduzido do domínio First Play, como se você estivesse inserindo o DVD pela primeira vez.

O sinalizador DVD_ResetOnStop é TRUE por padrão, para compatibilidade com aplicativos mais antigos. Geralmente, no entanto, você deve substituir o padrão e definir o sinalizador como FALSE. O motivo é que determinados eventos podem fazer com que o grafo pare durante a reprodução. Por exemplo, se a resolução de exibição for alterada, o grafo de filtro será interrompido, reconectará o renderizador de vídeo e reiniciará. Se DVD_ResetOnStop for TRUE, a reprodução será reiniciada desde o início do disco. Isso provavelmente não é o que o usuário espera.

No início do aplicativo, portanto, chame SetOption com DVD_ResetOnStop definido como FALSE. Se você quiser interromper a reprodução e retomá-la do mesmo local, chame IMediaControl::Stop ou IMediaControl::P ause. Se você quiser interromper a reprodução e redefinir o disco, chame SetOption com DVD_ResetOnStop igual a TRUE; em seguida, chame IMediaControl::Stop; por fim, chame SetOption novamente e redefina DVD_ResetOnStop como FALSE.

Pausando a reprodução

Se você der um comando ao Navegador de DVD enquanto o grafo estiver em pausa, o comando poderá não ser concluído até que o grafo seja executado novamente. Em algumas situações, isso pode causar um deadlock em seu aplicativo. Há duas regras que você deve seguir para evitar deadlocks:

  • Enquanto estiver em pausa, não emita mais de um comando de DVD assíncrono.
  • Enquanto estiver em pausa, não bloqueie o thread da interface do usuário do aplicativo ou o thread que altera o estado do grafo.

A segunda regra vale a pena examinar mais detalhadamente. Aqui estão alguns cenários específicos que podem causar um deadlock:

  • Cenário: enquanto pausado, o aplicativo emite um comando de DVD com o sinalizador de bloqueio. Isso poderá causar um deadlock se o thread que emite o comando DVD for o mesmo thread que emite o comando run. O comando DVD é bloqueado até que o grafo seja executado, mas o grafo não pode ser executado até que o comando seja concluído.

    Recomendação: emita o comando DVD em um thread de trabalho separado ou não use o sinalizador de bloqueio.

  • Cenário: enquanto pausado, o aplicativo emite um comando de DVD e chama IDvdCmd::WaitForEnd no objeto de comando. Essa situação é equivalente ao exemplo anterior. Se você chamar Wait do thread da interface do usuário, o thread da interface do usuário não poderá executar o grafo até que o método Wait seja desbloqueado, mas o método Wait não será desbloqueado até que o grafo seja executado.

    Recomendação: chame a espera em um thread de trabalho.

  • Cenário: enquanto o grafo está em execução, o aplicativo emite um comando de DVD com o sinalizador de bloqueio e, em seguida, chama pause de outro thread. Essa é uma possível condição de corrida porque o grafo pode pausar antes que o comando seja emitido. Se um dos dois threads for o thread da interface do usuário, você poderá causar um deadlock semelhante aos dois exemplos anteriores. Este exemplo ilustra a importância de escrever código thread-safe se o aplicativo usar vários threads.

    Recomendação: se você usar threads de trabalho, verifique se o código é thread-safe.

  • Cenário: enquanto pausado, o aplicativo desabilita o comando de execução da interface do usuário e, em seguida, emite um comando de DVD assíncrono. Esse caso não é estritamente um deadlock, porque o thread do aplicativo ainda está em execução. No entanto, o usuário agora está impedido de executar o grafo e, portanto, o comando nunca será concluído.

    Recomendação: ao pausar, sempre deixe o comando executar habilitado.

Buscando um DVD para um horário especificado

Para buscar com precisão uma hora especificada em um disco, chame IMediaControl::Run. Em seguida, chame IDvdControl2::P layAtTime, especificando a hora e a configuração de dwFlags como DVD_CMD_FLAG_Flush.

Aplicativos de DVD