【问题标题】:Playback large files on Windows Media Player during download下载期间在 Windows Media Player 上播放大文件
【发布时间】:2010-10-13 10:44:23
【问题描述】:

我的问题是关于将视频文件写入从网络下载的硬盘驱动器并同时使用 Windows Media Player 播放它。该文件很大,需要一段时间才能下载。需要下载而不是直接将其流式传输到 Windows Media Player。

发生的情况是,虽然我可以从我自己的测试代码中写入视频文件并同时读取它,但无法使用 Windows Media Player 完成(至少我还没有弄清楚)。我知道这是可能的,因为 Amazon Unbox 下载做到了。 Unbox 可让您在下载 WMV 时播放它们。而且 Unbox 是用 .NET 编写的,所以...

我已阅读“C# file read/write fileshare doesn’t appear to work”问题和答案,用于打开带有 FileShare 标志的文件。但这对我不起作用。进程监视器说媒体播放器正在打开带有文件共享标志的文件,但它出错了。

在缓冲线程中,我有这段代码用于从网络读取文件并将其写入文件(没有错误处理或其他使其更具可读性的东西):

// 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);
}

这似乎工作正常。该文件写入磁盘并具有正确的权限。

然后是另一个线程中用于播放视频的事件处理程序

    // the playback thread

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

Windows Media Player 指示它正在打开文件,然后停止并显示无法打开文件“已在另一个进程中打开”的错误。

我已经尝试了我能想到的一切。我错过了什么?如果亚马逊的人可以做到这一点,那么我也可以,对吧?

编辑: 此代码适用于 mplayer、VLC 和 Media Player Classic;只是不是 Windows Media Player 或 Windows Media Center 播放器。 IOW,我唯一需要他们合作的球员。啊!

编辑2: 我什至使用 MiniHttp 将视频流式传输到 Windows Media Player,看看这是否会“欺骗”WMP 播放正在下载的视频。无所事事。虽然 WMP 确实打开了文件,但它一直等到 mpeg 文件被完全复制后才开始播放。它是怎么知道的?

编辑3: 经过一番挖掘,我发现了问题所在。我正在处理 MPEG2 文件。问题不一定与 Windows Media Player 相关,而是与 Microsoft MPEG2 DirectShow Splitter 相关,WMP 使用它来打开我尝试同时播放和下载的 MPEG2 文件。拆分器以非共享模式打开文件。 WMV 文件并非如此。 WMP 以共享模式打开它们,一切正常。

【问题讨论】:

    标签: c# fileshare media-player


    【解决方案1】:

    我决定回答我自己的问题,以防其他人遇到这种罕见的情况。

    简短的回答是:Windows Media Player(在撰写本文时)将允许同时下载和播放文件,只要该功能受渲染文件所涉及的 CODECS 支持。

    引用问题的最后编辑:

    经过一番挖掘,我发现了问题所在。我正在处理 MPEG2 文件。问题不一定与 Windows Media Player 相关,而是与 Microsoft MPEG2 DirectShow Splitter 相关,WMP 使用它来打开我尝试同时播放和下载的 MPEG2 文件。拆分器以非共享模式打开文件。 WMV 文件并非如此。 WMP 以共享模式打开它们,一切正常。

    【讨论】:

      【解决方案2】:

      当您打开文件进行写入时,您不应使用 FileShare.ReadWrite。您应该改用 FileShare.Read:

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

      当 mplayer.exe 进程打开文件进行读取时,它会首先尝试使用 FileShare.Read 打开它,但会失败,然后它会重新尝试使用 FileShare.ReadWrite 来打开它,这会成功。

      【讨论】:

      • 不幸的是,这适用于 mplayer.exe、VLC 和 mplayerc.exe,但不适用于 Windows Media Player。希望我知道 Unbox 的人在做什么魔法。
      【解决方案3】:

      在@darin 发表评论后于 3 月 16 日更新:

      您在写入文件时指定FileShare.ReadWrite,理论上这也允许另一个进程打开它进行写入。

      尝试将您的代码更改为仅请求FileShare.Read

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

      引用MSDN

      FileShare.Read:允许后续 打开文件以供阅读。

      FileShare.ReadWrite:允许后续 打开文件以供阅读或 写作。

      【讨论】:

      • @Bevan,在创建文件时指定 FileShare.Write 意味着媒体播放器将永远无法打开文件进行阅读。
      • @darin - 感谢您的提醒。 FileShare 并不像我想象的那样。我已经更新了我的答案以适应我更好的理解。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多