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

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

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

Я прочитал вопрос " C # file read / write filehare не работает " и ответы на вопрос об открытии файла с флагами 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 указывает, что он открывает файл и затем просто останавливается с ошибкой, что файл не может быть открыт «уже открыт в другом процессе».

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 01 апреля 2009

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

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

Цитировать из последнего редактирования к вопросу:

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

0 голосов
/ 15 марта 2009

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

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

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

0 голосов
/ 15 марта 2009

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

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

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

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

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

FileShare.Read: разрешает последующее открытие файла для чтения.

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

...