BackgroundAudioPlayer是“玩”,但没有要求GetSampleAsync()(Ba

2019-08-17 15:53发布

我从一个后台代理网络使用自定义的媒体流的流媒体音乐。 在良好的网络条件下能正常工作,但是当网络连接是参差不齐的一个奇怪的问题表面。

当轨迹回放开始,一切顺利了通过第一次调用MediaStreamSource.GetSampleAsync()。 因为连接是参差不齐的,如果没有足够的数据可用源调用ReportGetSampleProgress(双),并返回而不报告的样本。 这是根据MSDN文档和代码示例。

什么是好奇的是,也有完全没有进一步呼吁GetSampleAsync! 作为缓冲继续,源继续ReportGetSampleProgress直到样品准备好了,当它调用ReportGetSampleProgress(1.0)以指示一个满的缓冲器。

我试过几种方法,其中包括:

  • ReportGetSampleCompleted当缓冲完成; 这种失败,因为下载的事件都在任意的线程,这种方法是既要调用线程以及是否GetSampleAsync调用是在栈上明显敏感; 无效的调用情况导致COM错误。
  • 在精确的错误情况,停止和启动BackgroundAudioPlayer:这个无法重新启动流。

我怎样才能再次流去,一旦最初的读取故障样本挂的东西呢?

Answer 1:

ReportGetSampleCompleted一旦数据可在这种情况下正确的做法。

你将不得不保持跟踪你的MSS是否需要立即报告任何新的样本数据或等待GetSampleAsync被调用。

但是看,由于竞争条件的故障是可能涉及到的各个线程之间。



Answer 2:

碰巧的是,一个解决问题的方法是打破由名称所建议的合同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);
}

这似乎是在一个异步方法阻止可能并不明智,但在设备上运行该代码的经验表明并非如此。 每http://msdn.microsoft.com/en-us/library/system.windows.media.mediastreamsource.getsampleasync(v=vs.95).aspx ,阻止可能阻止其他数据流不会被读取。 作为流媒体音乐应用程序,我们永远只能起到一个流的时间,所以在这种情况下,我们似乎很确定。

我希望我知道一个通​​用的解决方案在这里,虽然,因为这显然是欺骗。



Answer 3:

如果你没有任何可用的数据,则填补沉默的缓冲区并上报。 这会给你时间进行实时数据进去。

你要集中在你的沉默数据的数据到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 );

对韩国人的运气。



文章来源: BackgroundAudioPlayer is 'Playing' but not calling GetSampleAsync()