2

カスタムMediaStreamSourceを使用して、バックグラウンドエージェントでWebから音楽をストリーミングしています。良好なネットワーク状態ではこれは正常に機能しますが、ネットワーク接続が不安定な場合は奇妙な問題が発生します。

トラックの再生が開始されると、MediaStreamSource.GetSampleAsync()への最初の呼び出しですべてが順調に進みます。接続が不安定なため、十分なデータが利用できない場合、ソースはReportGetSampleProgress(double)を呼び出し、サンプルを報告せずに戻ります。これは、MSDNのドキュメントとコードサンプルに準拠しています。

不思議なのは、GetSampleAsyncへの呼び出しがこれ以上ないことです。バッファリングが続くと、ソースはサンプルの準備ができるまでReportGetSampleProgressを続行し、サンプルがいっぱいになるとReportGetSampleProgress(1.0)、バッファがいっぱいであることを示します。

私は次のようないくつかのアプローチを試しました。

  • ReportGetSampleCompletedバッファリングが完了したとき。ダウンロードイベントは任意のスレッドで発生し、このメソッドは呼び出し元のスレッドとGetSampleAsyncの呼び出しがスタック上にあるかどうかの両方に明らかに敏感であるため、これは失敗します。無効な呼び出し状況では、COMエラーが発生します。
  • 正確なエラー状態で、BackgroundAudioPlayerを停止して開始します。これにより、ストリーミングの再開に失敗します。

サンプルの読み取りに最初に失敗したときに問題が発生した場合、どうすればストリーミングを再開できますか?

4

3 に答える 3

1

利用可能なデータがない場合は、バッファを無音で埋めて報告してください。これにより、実際のデータが入るまでの時間が与えられます。

無音データの PCM 範囲の中央にデータを配置したい場合。そうしないと、無音になるときにクリック音が発生します。

MemoryStream stream = new MemoryStream();

byte[] silenceBuffer = BitConverter.GetBytes( (ushort)(short.MaxValue) );
for(int i=0; i < 1000; i++ )
    stream.Write( silenceBuffer, 0, silenceBuffer.Length );

幸運を祈ります。

于 2013-05-30T13:36:27.273 に答える
1

たまたま、解決策は名前によって提案されたコントラクトを破ることであり、GetSampleAsync十分なデータがバッファリングされていないときにそのメソッドでブロックするようです。その後、ストリーム コールバックはロックされたオブジェクトにパルスを送信し、サンプルの読み取りを再試行できます。このようなものはうまくいきます:

private void OnMoreDataDownloaded(object sender, EventArgs e)
{
    // We're on an arbitrary thread, so instead of reporting
    // a sample here we should just pulse.
    lock (buffering_lock) {
        is_buffering = false;
        Monitor.Pulse(buffering_lock);
    }
}

protected override void GetSampleAsync()
{
    while (we_need_more_data) {
        lock (buffering_lock) {
            is_buffering = true;
            while (is_buffering) {
                Monitor.Wait(buffering_lock);
            }
    }

    // code code code
    ReportGetSampleCompleted(sample);
}

Async メソッドでのブロックは賢明ではないように思われるかもしれませんが、デバイスでこのコードを実行した経験からすると、そうではないことが示唆されます。http://msdn.microsoft.com/en-us/library/system.windows.media.mediastreamsource.getsampleasync(v=vs.95).aspxによると、ブロックすると他のストリームが読み取られなくなる可能性がありますストリーミング音楽アプリとして、一度に 1 つのストリームしか提供しないため、この場合は問題ないようです。

ただし、これは明らかに不正行為であるため、ここで一般的な解決策を知っていればよかったのにと思います。

于 2013-03-17T05:12:56.343 に答える
1

ReportGetSampleCompletedこのシナリオでは、データが利用可能になった時点が正しいアプローチです。

新しいサンプルデータをすぐに報告する必要があるか、呼び出されるのを待つ必要があるかどうか、MSS で追跡する必要がありますGetSampleAsync

ただし、関連するさまざまなスレッド間で競合状態による障害が発生する可能性があることに注意してください。

于 2013-03-15T22:37:24.027 に答える