2

バックグラウンド

WebClient.OpenReadAsync/OpenReadCompleted と Stream.BeginRead/AsyncCallback を使用して、メディア ファイルを Silverlight 4 アプリケーションに段階的にダウンロードしています。目標は、SetSource メソッドを呼び出してカスタム MediaStreamSource のインスタンスを渡すことにより、MediaElement でファイルを再生することです。これにより、ファイルのコンテンツ全体がダウンロードされる前にファイルの再生を開始できます。メディア ファイルはカスタム エンコード/デコードを使用しているため、カスタム 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 つのストリームを含めることです。1 つは読み取り用、もう 1 つは書き込み用です。

GetSampleAsync() が呼び出されるたびに、書き込みストリームのバッファーを使用して、読み取りストリームを破棄して再作成します。それを行う別の方法は、MediaStreamSample を作成するときに負のオフセットを使用して ReportGetSampleCompleted() に渡すことです。これは、ストリームの位置が常に最後になるためです。それ以外の場合は、位置が最後にあることを確認する必要があります。これは機能しません。簡単にするために、2つのストリームを使用しました

于 2011-12-21T23:13:10.713 に答える