2

背景

我有一个媒体文件,我正在使用 WebClient.OpenReadAsync/OpenReadCompleted 和 Stream.BeginRead/AsyncCallback 逐步下载到我的 Silverlight 4 应用程序。目标是通过调用 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?

谢谢

4

1 回答 1

1

我在 MediaStreamSource 实现中的做法是在其中包含 2 个流:一个用于读取,一个用于写入。

每次调用 GetSampleAsync() 时,我都会使用写入流的缓冲区来处理和重新创建读取流。我猜另一种方法是在创建 MediaStreamSample 以传递给 ReportGetSampleCompleted() 时使用负偏移量,因为流的位置将始终位于末尾,但您必须确保该位置位于末尾这行不通,为了简单起见,我只使用了 2 个流

于 2011-12-21T23:13:10.713 回答