• [原]编程手记2008.08.28


    经过一天多的努力,疑神疑鬼了一大圈,终于稀里糊涂地找到播放速度变慢的原因了。。。

    先说一下发现的过程:

        开始一直感觉是buf写入过快导致的,因为所有的证据都反映出当buf写入速度放慢时播放速度趋于正常,但又实在是想不出个所以然来。。。
        由于不管buf写入快慢,写入前都要检测buf的WAVEHDR->dwFlags确定buf是否可写入。但。。。,反正就是怀疑到了检测正在播放中的buf的WAVEHDR->dwFlags会影响播放速度。
        一直以为只能根据通过检测WAVEHDR->dwFlags来确定数据是否已完成播放,代码别人写的,直接拿过来简单改了下,也未多想。昨天翻了下MSDN,发现还有一种回调函数的方式,waveOutOpen时可设置一个回调函数,一块数据播放完后,系统会调用这个函数。
        基于对检测WAVEHDR->dwFlags会影响播放速度的怀疑,改用了回调函数的方式。但修改后声音播放滞后的问题依然存在。因此,接着怀疑,即使buf中的数据播放完后不能立即写入,而是要稍等一会才能写@#$!。
        不过,没有接着将程序按上面假定修改。而是在偶然间播了一个mp3,发现不但播放滞后,还有噪声,解码器还间歇输出解码错误的信息。。。
        已经有一阵子没用mp3测程序了,记得以前播是很好的,翻出很早的一个版本一试果然如此。逐渐在之后的几个修改版本中试验,发现问题产生在修改了buf管理策略后(最初是收到数据立即解码的,但这样内存占用过高,因此改为将收到数据先保存,直到快要播放时才解码),因此基本可以确定是输入解码器的数据有误。
        但至此,还未将此错误与声音播放滞后联系起来,只是一个偶然的念头决定先将此问题解决后再寻找声音播放滞后的问题。接着就进入正轨了,在程序中加入状态输出代码后,解码器报错的出现时机有很强的规律性。在查看buf输入解码器的过程中,很快就发现buf数据块有重复输入解码器的可能,而且。。。这种情况在播放buf满(此时输入buf数据很充足)的情况下会非常严重,而这正是播放http链接时的典型特征。。。
        至此,已豁然开朗了,由于数据重复输入解码器,导致解码数据量增大,因此播方的时间就会变长。播放rtsp链接写入解码数据时,播放buf满的概率远小于http链接,因此,声音滞后的情况很难发现,而播放http链接时问题就凸现了,实质上,问题在播放rtsp和http链接中都是存在的。减慢写入数据的速度也正是可以减小播放buf满的概率。。。另外,由于播放的片子以说话为主,声音上的差异除了觉得说话声音变慢外较难听出其它差异,而换为音乐mp3后,差异就很明显了。

    总结:

        有时bug的真正根源与它的表现是相差很远的,发现bug难,找到bug真正的根源更难。。。现象是本质的反映,但很多情况下现象对本质的反映是很隐晦的,有时还很具有误导性。但我们要透过现象找到问题的本质。。。
        有时,找到问题的根源很具有偶然性,如何才能够将这种偶然转变为必然呢。。。
        曾经一度想通过减慢播放buf写入的速度纠正这个问题,不过还是抵制住了这种诱惑,因为这终究是治标不治本的做法,问题在其它条件下可能又会凸现出来。正像The Progmatic Programmer中教导我们的那样,要深思熟虑地编程,而不能基于巧合编程。
        虽然经常换用不同的序列测试,如不同的编码器、帧率等方面,但将单纯的音乐mp3忘记了很久,而这正是检验音频播放效果的最佳测试源。
  • 相关阅读:
    缩水版遗传算法 学习笔记
    算法导论 二项堆
    Linux系统编程(6)——文件系统
    Linux系统编程(5)——文件与IO之mmap函数
    Linux系统编程(4)——文件与IO之ioctl函数
    Linux系统编程(3)——文件与IO之fcntl函数
    Linux系统编程(2)——文件与IO之系统调用与文件IO操作
    Linux系统编程(1)——文件与I/O之C标准I/O函数与系统调用I/O
    C语言的本质(38)——makefile之变量
    C语言的本质(37)——makefile之隐含规则和模式规则
  • 原文地址:https://www.cnblogs.com/techsunny/p/1278735.html
Copyright © 2020-2023  润新知