Воспроизведение больших файлов в проигрывателе Windows Media во время загрузки.

StackOverflow https://stackoverflow.com/questions/647501

  •  22-07-2019
  •  | 
  •  

Вопрос

Мой вопрос заключается в записи видеофайла на жесткий диск, загружаемого из сети, и одновременном его воспроизведении с помощью проигрывателя Windows Media.Файл довольно большой, и его загрузка займет некоторое время.Его необходимо загрузить, а не просто транслировать непосредственно в проигрыватель Windows Media.

Происходит следующее: хотя я могу одновременно записывать видеофайл и читать его из своего собственного тестового кода, это невозможно сделать с помощью проигрывателя Windows Media (по крайней мере, я в этом не разобрался).Я знаю, что это возможно, потому что это можно сделать с помощью загрузок Amazon Unbox.Unbox позволяет воспроизводить файлы WMV во время их загрузки.А Unbox написан на .NET, так что...

Я прочитал "Чтение/запись файлов C#, общий доступ к файлам, похоже, не работает"вопрос и ответы по открытию файла с флагами FileShare.Но у меня это не работает.Process Monitor сообщает, что Media Player открывает файл с флагами 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 указывает, что он открывает файл, а затем просто останавливается с ошибкой о том, что файл не может быть открыт «уже открыт в другом процессе».

Я перепробовал все, что мог придумать.Что мне не хватает?Если ребята из Amazon могут это сделать, то смогу и я, верно?

редактировать:этот код работает с mplayer, VLC и Media Player Classic;но не проигрыватель Windows Media или проигрыватель Windows Media Center.IOW, единственные игроки, с которыми мне нужно работать.фу!

редактировать2:Я зашел так далеко, что использовал MiniHttp для потоковой передачи видео в проигрыватель Windows Media, чтобы посмотреть, «обманет» ли это WMP, заставив его воспроизвести загружаемое видео.Ничего не делая.Хотя WMP и открывал файл, он ждал, пока файл mpeg не будет полностью скопирован, прежде чем начать воспроизведение.Откуда оно знает?

редактировать3:После некоторого копания я обнаружил проблему.Я работаю с файлами MPEG2.Проблема не обязательно в проигрывателе Windows Media, а в Microsoft MPEG2 DirectShow Splitter, который WMP использует для открытия файлов MPEG2, которые я пытаюсь воспроизвести и загрузить одновременно.Splitter открывает файлы в режиме без общего доступа.С файлами WMV дело обстоит иначе.WMP открывает их в общем режиме, и все работает как положено.

Это было полезно?

Решение

Я решил ответить на свой вопрос на случай, если кто-то еще столкнется с этой редкой ситуацией.

Краткий ответ таков:Проигрыватель Windows Media (на момент написания этой статьи) позволит одновременно загружать и воспроизводить файл, если эта функциональность поддерживается CODECS, участвующим в рендеринге файла.

Цитирую последнее изменение вопроса:

После некоторого копания я обнаружил проблему.Я работаю с файлами MPEG2.Проблема не обязательно в проигрывателе Windows Media, а в Microsoft MPEG2 DirectShow Splitter, который WMP использует для открытия файлов MPEG2, которые я пытаюсь воспроизвести и загрузить одновременно.Splitter открывает файлы в режиме без общего доступа.С файлами WMV дело обстоит иначе.WMP открывает их в общем режиме, и все работает как положено.

Другие советы

Когда вы открываете файл для записи, вам не следует использовать FileShare.ReadWrite.Вместо этого вам следует использовать FileShare.Read:

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

Когда процесс mplayer.exe открывает файл для чтения, он сначала попытается открыть его с помощью FileShare.Read, что завершится неудачей, но затем повторит попытку с помощью FileShare.ReadWrite, которая завершится успехом.

Обновлено 16 марта после комментария @darin:

Вы указываете FileShare.ReadWrite когда вы пишете файл, что теоретически позволяет другому процессу открыть его и для записи.

Попробуйте изменить свой код, чтобы он только запрашивал FileShare.Read:

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

Цитировать MSDN:

FileShare.Читать:Допускает последующее открытие файла для чтения.

FileShare.ReadWrite:Допускает последующее открытие файла для чтения или писать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top