背景
我有一个媒体文件,我正在逐步下载到我的Silverlight 4应用程序,使用WebClient.OpenReadAsync / OpenReadCompleted和Stream.BeginRead / AsyncCallback。目标是通过调用SetSource方法在MediaElement中播放文件,传入我们的自定义MediaStreamSource的实例,以便文件可以在下载文件的整个内容之前开始播放。媒体文件使用自定义编码/解码,这就是我们使用自定义MediaStreamSource的原因。我们的MediaStreamSource构建为接受Stream并开始解析轨道信息并在MediaElement中播放。我已经确认我正在逐步下载文件内容。以下是下载代码的摘要:
public void SetSource(string sourceUrl)
{
var uriBuilder = new UriBuilder(sourceUrl);
WebClient webClient = new WebClient();
// AllowReadStreamBuffering = false allows us to get the stream
// before it's finished writing to it.
webClient.AllowReadStreamBuffering = false;
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(uriBuilder.Uri);
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
_inboundVideoStream = e.Result;
BeginReadingFromStream();
}
private void BeginReadingFromStream()
{
if (_inboundVideoStream.CanRead)
{
_chunk = new byte[_chunkSize];
_inboundVideoStream.BeginRead(_chunk, 0, _chunk.Length, new AsyncCallback(BeginReadCallback), _inboundVideoStream);
}
}
private void BeginReadCallback(IAsyncResult asyncResult)
{
Stream stream = asyncResult.AsyncState as Stream;
int bytesRead = stream.EndRead(asyncResult);
_totalBytesRead += bytesRead;
if (_playableStream == null)
_playableStream = new MemoryStream();
_playableStream.Write(_chunk, 0, _chunk.Length);
if (!_initializedMediaStream && _playableStream.Length >= _minimumToStartPlayback)
{
_initializedMediaStream = true;
// Problem: we can't hand the stream source a stream that's still being written to
// It's Position is at the end. Can I read and write from the same stream or is there another way
MP4MediaStreamSource streamSource = new MP4MediaStreamSource(_playableStream);
this.Dispatcher.BeginInvoke(() =>
{
mediaElement1.SetSource(streamSource);
});
}
if (_totalBytesRead < _fileSize)
{
ReadFromDownloadStream();
}
else
{
// Finished downloading
}
}
我已经尝试过同时写入/读取MemoryStream,如上所列,以及写入IsolatedStorageFile并在写入时从该文件读取。到目前为止,我无法找到一种方法来使这两种方法都有效。
问题:
有没有办法读取和写入相同的流?或者是否有一种标准的方法来实现流和MediaStreamSource?
由于
答案 0 :(得分:1)
我在MediaStreamSource实现中的方式是在其中包含2个流:一个用于读取,一个用于写入。
每次调用GetSampleAsync()时,我都会使用写入流的缓冲区来处理和重新创建读取流。另一种方法我猜测是在创建MediaStreamSample时使用负偏移量传递给ReportGetSampleCompleted(),因为流的位置总是在最后,但你必须确保位置在最后这是行不通的,为了保持简单,我只使用了2个流