2009-03-15 4 views
2

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

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

Я прочел вопрос «C# file read/write fileshare doesn’t appear to work» и ответил, открывая файл с флагами 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); 
} 

Это похоже на работу хорошо. Файл записывается на диск и имеет правильные разрешения.

Но Heres обработчик событий в другом потоке для воспроизведения видео

// the playback thread 

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

Windows Media Player указывает, что его открытие файла, а затем просто останавливается с ошибкой, что файл не может быть открыт «уже открыт в другом процессе».

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

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

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

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

ответ

2

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

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

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

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

0

Обновлено 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: разрешает последующие открытие файла для чтения или запись.

+0

@Bevan, указав FileShare.Write при создании файла, означает, что медиа-плеер никогда не сможет открыть файл для чтения. –

+0

@ дарин - спасибо за головы. FileShare не означает, что я думал, что это так. Я обновил свой ответ в соответствии с моим улучшенным пониманием. – Bevan

0

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

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

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

+0

К сожалению, это работает для mplayer.exe, VLC и mplayerc.exe, но не для Windows Media Player. Хотелось бы, чтобы я знал, какая магия ребята из Unbox делали. – CLaRGe