Pergunta

A minha pergunta é sobre a escrita de um arquivo de vídeo para o disco rígido que está sendo baixado da rede e jogá-lo ao mesmo tempo usando o Windows Media Player. O arquivo é muito grande e vai levar algum tempo para baixar. É necessário baixá-lo ao invés de apenas transmiti-lo diretamente para o Windows Media Player.

O que acontece é que, enquanto eu posso escrever para o arquivo de vídeo e lê-lo, ao mesmo tempo do meu próprio código de teste, não pode ser feito usando o Windows Media Player (pelo menos eu não percebi isso). Eu sei que é possível fazer porque a Amazon Unbox de downloads faz. Unbox permite que você jogue WMVs enquanto ele está baixando-los. E Unbox está escrito em .NET assim ...

Eu li o " C # arquivo de leitura / gravação não fileshare não aparecem para trabalhar " perguntas e respostas para a abertura de um arquivo com as bandeiras FileShare. Mas ele não está funcionando para mim. Process Monitor diz que Media Player está abrindo o arquivo com bandeiras FileShare, mas ele erros fora.

No segmento de buffer Eu tenho esse código para a leitura do arquivo da rede e escrevê-lo em um arquivo (sem tratamento de erros ou outras coisas para torná-lo mais legível):

// the download thread
void StartStreaming(Stream webStream, int bufferFullByteCount)
{
    int bytesRead;
    var buffer = new byte[4096];
    var fileStream = new FileStream(MediaFile.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
    var writer = new BinaryWriter(fileStream);
    var totalBytesRead = 0;
    do
    {
        bytesRead = webStream.Read(buffer, 0, 4096);
        if (bytesRead != 0)
        {
            writer.Write(buffer, 0, (int)bytesRead);
            writer.Flush();
            totalBytesRead += bytesRead;
        }
        if (totalBytesRead >= bufferFullByteCount)
        {
            // fire an event to a different thread to tell 
            // Windows Media Player to start playing
            OnBufferingComplete(this, new BufferingCompleteEventArgs(this, MediaFile));
        }
    } while (bytesRead != 0);
}

Este parece funcionar bem. O arquivo grava no disco e tem as permissões corretas.

Mas então aqui está o manipulador de eventos no outro segmento para reproduzir o vídeo

    // the playback thread

private void OnBufferingComplete(object sender, BufferingCompleteEventArgs e)
{
    axWindowsMediaPlayer1.URL = e.MediaFile.FullName;
}

Windows Media Player indica que sua criação do ficheiro e, em seguida, simplesmente pára com um erro que o arquivo não pode ser aberto "já abriu em outro processo."

Eu tentei tudo que eu posso pensar. o que estou perdendo? Se os caras da Amazon pode fazer isso, então eu também posso, certo?

edit: esse código funciona com o MPlayer, VLC, e Media Player Classic; apenas não o Windows Media Player ou Windows Media Player Center. IOW, os únicos jogadores que eu precisar deles para trabalhar. ugh!

edit2: Eu fui tão longe para usar MiniHttp para transmitir o vídeo para o Windows Media Player para ver se que "enganar" WMP em jogar um vídeo que está sendo download. Nada a fazer. Enquanto WMP fez aberto o arquivo, ele esperou até que o arquivo mpeg foi completamente copiado antes que ele começou a tocar. Como ele sabe?

edit3: Depois de algumas escavações eu descobri o problema. Eu estou trabalhando com arquivos MPEG2. O problema não é necessariamente com o Windows Media Player, mas com a Microsoft MPEG2 DirectShow Splitter que WMP usa para abrir os arquivos MPEG2 que estou tentando jogar e baixar ao mesmo tempo. O Splitter abre os arquivos no modo não-Shared. Não é assim com arquivos WMV. WMP abre-los no modo e tudo funciona compartilhados como esperado.

Foi útil?

Solução

Decidi responder a minha própria pergunta no caso de alguém corre para esta situação rara.

A resposta curta é esta:. Windows Media Player (como esta escrito) permitirá que um arquivo a ser baixado e jogar ao mesmo tempo, enquanto que a funcionalidade é apoiado por CODECS envolvidos na prestação do arquivo

Para citar a última edição para a pergunta:

Depois de algumas escavações eu descobri o problema. Eu estou trabalhando com arquivos MPEG2. O problema não é necessariamente com o Windows Media Player, mas com a Microsoft MPEG2 DirectShow Splitter que WMP usa para abrir os arquivos MPEG2 que estou tentando jogar e baixar ao mesmo tempo. O Splitter abre os arquivos no modo não-Shared. Não é assim com arquivos WMV. WMP abre-los no modo e tudo funciona compartilhados como esperado.

Outras dicas

Quando você abre o arquivo para escrever você não deve usar FileShare.ReadWrite. em vez disso você deve usar FileShare.Read:

var fileStream = new FileStream(
    MediaFile.FullName, FileMode.Create, FileAccess.Write, FileShare.Read);

Quando mplayer.exe processar abrir o arquivo para leitura vai primeiro tentar abri-lo com FileShare.Read que irá falhar mas, em seguida, vai tente novamente com FileShare.ReadWrite que terá sucesso.

Updated 16 de março depois de comentário por @darin:

Você está especificando FileShare.ReadWrite quando você está escrevendo o arquivo, o que teoricamente permite que outro processo para abri-lo para escrever também.

Tente alterar o seu código apenas FileShare.Read pedido:

var fileStream 
    = new FileStream(
        MediaFile.FullName, 
        FileMode.Create, 
        FileAccess.Write, 
        FileShare.Read); // Instead of ReadWrite

Para citar MSDN :

FileShare.Read: Permite posterior abertura do arquivo para leitura.

FileShare.ReadWrite: Permite posterior abertura do arquivo para leitura ou escrita.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top