Мой вопрос касается записи видеофайла на жесткий диск, который загружается из сети, и одновременного воспроизведения его с помощью проигрывателя 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 открывает их в режиме совместного использования, и все работает как положено.