收藏 分销(赏)

数字语音教室中DirectShow的应用论文.doc

上传人:仙人****88 文档编号:9149493 上传时间:2025-03-15 格式:DOC 页数:24 大小:315KB 下载积分:10 金币
下载 相关 举报
数字语音教室中DirectShow的应用论文.doc_第1页
第1页 / 共24页
数字语音教室中DirectShow的应用论文.doc_第2页
第2页 / 共24页


点击查看更多>>
资源描述
毕业论文 第21页 数字语音教室中DirectShow的应用 摘 要 随着信息技术的高速发展,教育产业的信息化势在必行,数字语音教室的高速发展和普及即将来临,它也将为学生提供更丰富、优秀的学习资源和条件,对学生在外语学习的听、说、讲三方面都有大有裨益,必将大大提高学校的教学质量。 本课题针对学校数字语音教室的需求,设计并实现了基于纯软件的一个简化版本的数字语音教室。数字语音系统中比较关键的语音处理部分。语音处理需要经过网络两端的共同协作来达到音频互动的效果。本系统采用Directshow框架,基于Visual stuio 2005。NET开发平台, 通过声音的捕捉、压缩、网络传送、解压、回放流程来实现语音的实际需要。通过结合Directshow框架,针对用于网络环境的多媒体程序,开发了发送和接收两个FILTER,对学生分组实现灵活控制,优化声音音质,对存储压缩,网络带宽优化等问题进行了有效的解决。 基于Directshow框架的语音处理是一个十分成熟的技术框架,在此之上建立的数字语音系统无疑将具有广泛的扩展空间。 关键字: 数字语音, DIRECTSHOW , 组播 The Appliance Of Directshow In Digital Audio Room Abstract With the rapid increasing of Information Techalog,Educational methods with a new fashion are exhibited for us,the emergence of Multimedia Room is especially typical.Digital Room is the important part of Multimedia Room.Most of the Multimedia Room is relative to analogue systems somehow.they have many inevitable shortages in compare to the Digitial Room.Therefor ,the development of Pure Digital Room has very import theortical and pratical vaule. The Pure Digital Room is design for Teaching requirment.it implement a simple voice Chat system.The whole system is make up of five process: Capture,Pre-Process,Sending, Receiveing,Post-Process and play.with the Directshow Framework,what we need to do is just develop two filters for sending and receiving. The Pure Digital Room has been conducted in foreign lanuage education successfully. With extending ,it can be used in WLAN ,Just like Tele-Education.But it still need more and more improvement. Keyword: Directshow , Mutlicast , Digital Audio 目录 摘 要 I Abstract II 1.绪论 1 1.1概念及其现状 1 1.2数字语音教室的概念及其发展 1 1.3 数字语音教室的市场前景 2 1.4 语音教室的市场前景 2 1.5语音处理 2 2.技术基础 3 2.1 COM 3 2.2 Directshow 3 2.3 Multicast 4 3. 语音处理模块 6 3.1处理环节 6 3.2 Graph的构成 7 3.3从始至终的声音样本 8 4. 声音的捕捉和回放 10 4.1声音的捕捉 10 4.1.1 声音捕获过滤器 10 4.1.2 声音捕获属性 10 4.3声音的回放 11 5压缩和解压 12 5.1压缩格式的选择 12 5.2声音的压缩 12 5.3 声音的解压 13 6网络传输 14 6.1组播传输 14 6.2声音的压缩 14 6.2.1 过滤器类型 14 6.2.2 选择父类 16 6.2.3 实现Filter 16 6.3数据的发送 17 6.4数据的接收 18 结论 19 致谢 20 参考文献 21 1.绪论 1.1概念及其现状 多媒体语音教室是现代化的外语教学设备,它不仅意味着教学模式上的飞跃,更在教学上更带来了很多的实际效果。它让学生摆脱了最初的只听老师讲的原始学习状态,让学生自己从以往那种只是读和听的学习过程转移到更好的参与互动讨论,动口说,用耳听,用眼看,使开发大脑加工多种形式的能力成为可能。它将质量更好的读、写和看结合到一起,为学生提供一个更好的思维训练和学习的平台。 最早出现的语音教室是由单一的麦克风和传音设备所组成的类似于对讲机的原始设备,很快,它并为添加了各种各样的多媒体设备的多媒体语音教室所代替,这个时候的语音教室大都由一些投影仪、幻灯机和录音机所拼接而成,在相当长的一段时间后,一整套的带有控制器的语音设备开始流行于各个学校之内,但是这个时候的语音教室还是基于硬件所建立的,我们将其成为传统的语音教室。 1.2数字语音教室的概念及其发展 随着现代信息化得发展,我们也看到了传统的基于硬件的系统所带来的局限性,外围教学工具缺少,媒体应用范围单一,灵活控制不够,课件的传统和单一,这些都逐步突显出来,如何才能更好的组织学生参与到学习过程中成为一个急待解决的问题。从信息理解的角度来看,由视觉传递的信息能被理解的为83%,由听觉传递的信息能被理解的为11%,由触觉传递的信息能被理解的为3%,其余的不到4%,而由视觉和听觉相结合产生的效果大于任何一个前者。显然,从效果来看,想要提高的话,最有效率的途径,也是空间最大的,是加大视觉的输入。,但这也是传统的多媒体教室所不具有的优势,这个时候,出现在人们眼前的PC网络却正好在这方面有着强大的优势,既而由此而产生的数字语音系统正好能给语音教室带来一个全新的诠释。数字语音教室是在建立在PC和网络上的纯数字音频系统,它将人声通过电脑和网络传送到另一端的电脑终端,通过模拟/数字转换实现语音交流,并且在这之上添加一系列权限控制。它具有良好的音质,性价比较高,容易推广,在极大的满足教学需求的同时,又合理的利用了有限的教学资源。它不仅支持传统语音的功能,还支持数字化广播,可视化视音频的点播,上课内容储存等更新的功能。 如何将语音教室发展得更为成熟和强大将是未来一个很重要的课题,数字语音所具有的优势还需要我们进一步的发现和集成,在数字语音的研究上面,我们还有很多方面需要改进,如如何将延迟减为更小,如何把混音处理做得更好等一系列难题需要解决。 1.3 数字语音教室的市场前景 总体来说,语音教室在国内外都具有很大的市场价值,由于数字系统不同于硬软或者硬件系统,它并不需要较大的投入,而且它本身由于是依附于PC,因此操作方便,简单,容易推广。从商业和学术上来说,都值得我们投入更多的力量。 1.4 语音教室的市场前景 数字教室作为一个整体的教学辅助手段,与传统的教学方式上有很大的区别。在上课时,学生可以参与分组讨论,在线提问和交流,同步观看老师的教学课件,浏览多媒体教学动画,甚至在PC时进行考试,而老师能在上课时对学生的PC进行远程控制,同时对学生说话的权利能进行有效控制,以保证上课的顺利进行,除此之外,对于外语教学所需要的步进,重复,跟读等有必须有完善的功能提供。但这中间最为关键的还是语音处理这一块,多套系统之间的竞争所凭的质量也就完全靠语音互动的效果。本文提出的基于Directshow的语音处理解决方案也就是完全为了改善语音处理的性能。 1.5语音处理 API 、Directsound、Directshow等各种技术都在语音处理方面有强大的支持。 总体来说,各种处理方案都包括捕获,压缩,传输,回放等步骤。最早出现的是API的方式,其后是Directsound,再后是Directshow。Directshow是3种最为成熟的技术。采用Directshow来实施语音处理从理论上来说是最为理想的。 2.技术基础 2.1 COM DIRECTX采用了COM标准,而DIRECTSHOW本身就是一套完全基于COM的应用系统,因为DIRECTSHOW本身就是一大的框架,在这个框架下你可以很容易的利用现有的COM实现你所需要的视频,音频上的相关处理。主要的组件FILTER,PIN等都是一个个的COM组件。 COM组件有3中类型:进程内,本地和远程组件,FILTER一般是进程内的组件,以AX的方式发布。每个COM组件一般都会提供一个ICALASSFACTORY接口,让使用者可以使用NEW操作生成一个COM组件实例。同时,COM组件的引用计数要求,在计数为0时会自动销毁,而用NEW产生时并不会添加引用,所以在这个时候你需要手动添加引用。 2.2 Directshow DIRECTSHOW从DIRECTSHOW SDK 2005(FEB)以后就从DIRECTX SDK中脱离出来单独成为一个SDK了,这说明它在多媒体的处理上有一定的集成了。它不仅兼容早期的VDF,WDM,也支持DMO,更为强大的是它允许开发人员自己定义适合自己的FILTER来扩充库。它广泛的支持各种媒体格式,包括ASF,MPEG,AVI,DV,MP3甚至RM,RMVB。 图1.1 Directshow应用程度 图1.1中央最大的一块即是DirectShow系统。DirectShow使用一种叫Filter Graph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫做Filter;各个Filter在Filter Graph中按一定的顺序连接成一条“流水线”协同工作。按照功能来分,Filter大致分为三类:Source Filters、Transform Filters和Rendering Filters。Source Filters主要负责取得数据;Transform Fitlers主要负责数据的格式转换、传输;EnderingFiltes主要负责数据的最终去向。FILTER也可以协同工作。在DirectShow系统之上,我们看到的,即是我们的应用程序(Application)。应用程序要按照一定的意图建立起相应的Filter Graph,然后通过Filter Graph Manager来控制整个的数据处理过程。DirectShow能在Filter Graph运行的时候接收到各种事件,并通过消息的方式发送到我们的应用程序。这样,就实现了应用程序与DirectShow系统之间的交互。下图给出了DirectShow应用程序开发的一般过程: 图1.2 Filter Graph Manager 2.3 Multicast 网络中的数据传输模式可以分为三类,单播,组播和广播。组播是基于UDP的,数据接收者是加入组播的PC。由此,它比较适合LAN内的媒体数据分发。常应用于多媒体方面,如VOD。组播的组地址使用的是D类地址,范围在224.0.0.0 to 239.255.255.255之间。对于发送者来说,数据如同单播一样照样发送,而对于接收着,在接收数据前必须加入特定的组播。 图1.3 组播网络 3. 语音处理模块 3.1处理环节 语音的互动实现是本系统十分关键的部分,对系统的运作性能有至关重要的影响,对于整套声音的处理其实有几套技术方案,以前如API, Direcdsound都在这方面比较成熟,有比较好的语音聊天作品,但是遗憾的是他们对于格式的扩展和灵活转换上支持不强,不同的网络可能需要不同的压缩格式和混音方式,同时,系统可能向视频演进,这样以后的系统开发就不得不重新考虑架构了。 语音互动是通过在网络发送,接收两端共同协作完成的,在一端,声音被捕获,可能经过预处理,然后传送到另一端,又经过预处理,然后被回放。这中间可分为:捕获和回放,压缩,解压,网络传输这几个部分。整个语音处理就可以被封装成一个功能模块,提供说话和收听功能。 图2.1整体流程 就单单声音的捕获和回放说,可以基于Directshow来完成,而但由于在Directshow仅仅提供的是从捕获到回放单机所需要的过滤器,那么涉及到网络的部分就需要自己开发过滤器,处理网络部分,这就要求开发人员自己开发网络过滤器。另一方面,声音样本直接被发送的话,可能会不大适宜,存储量对PC和网络将是一个巨大的挑战,所要预处理时需要将样本进行压缩,接收时需要解压。如下图所示,图中每个方框代表一个过滤器,却又是一个处理处理环境,(Smart Tee Filter是可选,它便于录音时使用),每一个处理环节在本文将分节讨论。 图2.2语音处理流程 在LAN的情况下,声音从一端被捕捉到网络的另一端被回放需要经过捕捉,压缩和网络传输,解压和回放这几个处理环节,如果按照端到端的角度来看,那么可以把网络发送看做一个最终的声音RENDER 过滤器,把声音的接收看成一个Source 过滤器,那么需要构件2个完整而独立的Filter Graph即可实现我们所需要的功能。 3.2 Graph的构成 在Directshow中,一个完整的处理程序都是建造在Graph中,Graph是由过滤器连接而构成的过滤器连接。数据从最上面一个过滤器跑到最下面一个过滤器,完成它所有的数据处理。每个过滤器都需要被添加到连中才能完成自己的效果。在声音的源端我们将构建如下的Graph: 图2.3 源端Graph 在数据接收端,GRAPH中的FILTER如下: 图2.4接收端Graph 其中SENDER和RECEIVER都是自定义生成的。声音从麦克风中以模拟信号的形式经过A/D转换成数字信号,经过MP3过滤器的转换,变成MP3格式的数据包,然后经Sender过滤器发送到网络中。Receiver负责从网络中拾取数据包,然后传递到下游的DECODER中,经其解压缩,然后发到Render中被播放。 当接收端的Graph连接成功后并不能立即开始启动,它会停留在暂停状态,由于这时候没有数据流入。一旦Receiver压入从网络中接收的数据样本时,接收Graph立即开发传送数据。 3.3从始至终的声音样本 语音数据是以声音样本的形容贯穿整个处理流程的,每个样本是CMediaSample来具体化,CMediaSample是由每个PIN负责维护的,它有一个指向内存快的指针,所存储的就是真正的音频格式数据。利用网络发送数据也就是将这块内存中的东西完全照搬。 声音样本通过一个媒体类型(CMediaType)来定义其格式,媒体类型是描述数字媒体格式的一种通用的可扩展方式。两个过滤器相连时,必须使用一致的媒体类型,否则这两个过滤器就不能相连。媒体类型能识别上一级过滤器传送给下一级过滤器的数据类型,并对数据进行分类。实际在很多应用程序中,用户根本不需要担心媒体类型的问题,DirectShow会处理好所有的细节。但有些应用程序需要对媒体类型进行操作。媒体类型一般可以有两种表示:AM_MEDIA_TYPE和CMediaType。 typedef struct _MediaType { GUID majortype; GUID subtype; BOOL bFixedSizeSamples; BOOL bTemporalCompression; ULONG lSampleSize; GUID formattype; IUnknown *pUnk; ULONG cbFormat; [size_is(cbFormat)] BYTE *pbFormat; } AM_MEDIA_TYPE; 前者是一个结构,后者是从这个结构继承过来的类。 4. 声音的捕捉和回放 4.1声音的捕捉 4.1.1 声音捕获过滤器 DirectShow对硬件的支持是通过特定的包装Filter来实现的。声卡使用的是Audio Capture Filter,Filter内部使用以waveIn开头的一套API实现(如waveInOpen等)。运行GraphEdit,插入Filter时,在“Audio Capture Sources”目录下,我们就能看到所有代表本地机器上的声卡的各个Filter(有的机器装了几张声卡,这里就会有几个Filter)。在Filter Graph中加入这个Filter,我们发现这个Filter有很多Input pin,如Line In、CD Audio、Microphone、Stereo Mix等等;有一个Capture output pin。需要说明的是,在Filter Graph中,这些Input pin并没有真正的数据流入,它们只是声卡的各个输入端子的象征性表示;所以这些Input pin永远也不用连接。 Directshow 允许直接将声卡里的模拟输入转换成硬盘可存储的各种格式,通过一个Audio Capture Filter封装了所有的功能。每一个声卡都可以通过一个过滤器被枚举出来从而加入到捕捉Graph中。对于声卡的各种输入选项如声音大小,BASS,TREBLE和PAN等声音捕捉过滤器都提供了相对应的接口。 建造一个声音捕获的Graph首要的是添加声音捕捉过滤器到Graph中,虽然所有的过滤器都是COM组件,但是不同于一般的过滤器,由于它涉及到低层硬件,不能通过简单的调用CoCreaeInstance函数来创建它,相反,需要调用系统设备枚举的途径,在特定的设备目录下才能找到它,然后调用相对应的名字绑定对象的类似于命名服务的方法使用。在Directshow中,所有涉及到硬件的,都需要通过此类途径来生成一个新的过滤器。 4.1.2 声音捕获属性 Directshow不仅仅对声音的捕捉做了支持,同时对于捕捉样本的大小和速度都有很好的支持。IAMAudioInputMixer接口是每一个声音捕捉过滤器都提供的接口,通过它可以允许或者禁止特定的输入和输出。甚至可以同时捕获多种输入。声音的采样率和声音格式是由硬件决定的,通过IAMStreamConfig接口我们可以枚举所可用的采样率和格式。一般来说,声音捕捉时都将有一定的延迟,通过过滤器上的IAMBufferNegotiation 接口, 我们可以改善这个性能。 4.3声音的回放 声音的捕捉和回放其实在实质上相反,前者将模拟信号转换成数字信号,后者将数字信号转换成模拟信号,同样在Directshow中,声音的播放不象捕获那样复杂,需要设定很多东西,它仅仅需要一个过滤器即可。对于多声卡的系统,同样对于每一个声卡,在过滤器列表中都有相对应的过滤器。 声音可以在一端捕获,在2端同时回放。由于在Directshow中包含一写重复数据过滤器,可以将样本数据复制一分,这样可以在说话的同时让自己和别人都能听到说话的内容。 由于在接收端,可能接收的声音并不一定来自同一端,这样各个声音样本到达接收端的时间可能发生颠倒,导致在回放时与本来的顺序出现误差,所以需要缓存后再进行混音。混音时需要特别注意,每个声音样本在被接收时会被设置一个时间戳,这个时间戳对于Render过滤器来说,就是样本的播放时间,这个时间戳就可以用来同步各个不同的声音播放时间,按照样本的时间从缓存中挑取最早的予以播放这样可以尽可能的避免声音的乱序。 声音在到达接收端一定会发生延迟,在声音还在发送端时就已经不可避免的发生了稍许延迟,但这对于人类来说是可以容忍的,特别是在实时性要求不是很高的时候。我们可以通过Capture output pin上的IAMBufferNegotiation接口,改变音频捕捉缓冲的大小,以减少声音播放的延迟。默认情况下,Audio Capture Filter使用0.5秒钟的缓冲。对于一些特殊的应用,这么大的缓冲是没有必要的,带来的延迟也比较大。一般,缓冲设置成能够容纳80毫秒的数据已经很可靠;甚至30-40毫秒也已经足够了。但是也不能太小,否则会影响到音频捕捉的效率,使音质受到损害。 5压缩和解压 5.1压缩格式的选择 一般通过声音捕获过滤器所传下来的Media Sample为80K左右,甚至达到了90多K,对于网络和PC来说无疑是不可行的,这就需要对声音进行预先处理,将声音样本转换为其他格式。目前的压缩方式比较多,如AAC, AC, CD, WAV,PCM等。算法不同,所得的效果也不同,而且数据是需要即时发送的,发送源的数目也可能变化,那就意味着数据量可能很大,这样尽可能高的压缩比将是首选。 在Directshow SDK中也提供了许多压缩过滤器,MP3,AC,PCM都在其中。 MP3的全称是MPEG(MPEG:Moving Picture Experts Group) Audio Layer-3,1 MP3是一种有损的压缩方式,早期的MP3编码采用的的是固定编码率的方式(CBR ),我们常看到的128KB/S,就代表每秒的数据流量有128KBIT,而且是固定的,这个称之为比特率,比特率本身是可以改变的,最高可以到320KBPS,当然比特率越高音质越好,但是文件的体积会相应增大。 因为MP3的编码方式是开放的,你可以在这个标准框架的基础上自己选择不同的声学原理进行压缩处理,所以,很快由Xing公司推出可变编码率的压缩方式(VBR)。它的原理就是利用将一首歌的复杂部分用高 bitrate 编码,简单部分用低 bitrate 编码,通过这种方式,进一步取得质量和体积的统一。当然,早期的Xing 编码器的 VBR 算法很差,音质与 CBR (固定码率)相去甚远。但是,这种算法指明了一种方向,其他开发者纷纷推出自己的VBR算法,使得效果一直在改进 。 而在VBR的基础上,LAME更加发展出ABR算法。 通过枚举MP3压缩过滤器,可以很方便的把MP3编码器加入到Graph中来。同时解码也很简单。开发人员所需要做的就是仅仅生成一个过滤器,然后连接上,下游过滤器,比起传统的算发的压缩,具有高效率,快速简单的优点。 5.2声音的压缩 MP3压缩过滤器的生成类似于声音捕捉过滤器,需要通过枚举,然后通过类似于命名服务的方式绑定生成。压缩过滤器的生成和添加不同于普通的过滤器,具体来说需要经过以下步骤,首先,生成系统枚举器通过CoCreateInstance。类标志符为CLSID_SystemDeviceEnum。然后,或者压缩过滤器类ICreateDevEnum::CreateClassEnumerator枚举器,它将返回一个IEnumMoniker类,遍历IEnumMoniker来获得所要的压缩器的IMoniker,最后用IMoniker::BindToObject来生成目标对象,生成后IFilterGraph::AddFilter添加到Graph中。 5.3 声音的解压 由于Directshow采用的是智能连接,在某种程度上来说,减轻了开发人员很多负担,只需要记住声音所具有的格式。前面我们才用MP3格式的压缩方式,解码时自然需要采用MP3 DECODE。 图5.1 Filter列表 它是一个普通的转换过滤器,生成后添加到Graph中即可。由于必须是样本数据经过这个Filter,所以在连接Filter时需要按照特定的顺序进行连接。不然在播放过滤器中可能无法识别该数据,可能导致播放时没有声音。 6网络传输 6.1组播传输 由于是网络多媒体,所以自然需要涉及到网络的处理。如何将媒体数据发送到网络中间去呢?和WIN32中的HOOK一样,DIRECTSHOW提供了这样的函数,在这样的函数中,你可以对数据进行处理,前提是你有一个比较好的网络实现。 在一个实现较好的组播网络中,数据从一端流到另一端,对上层来说相对透明,这样的程序自然便于移植和开发。在发送端,我们可不大考虑数据线程的独立性和同步性,因为它只是一个上游驱动的发送机,当网络发送过滤器这个FILTER接收到上游FILTER发送过来的数据包时,它很自然把数据通过网络接口发送到组播地址中,甚至连它自己都不必要在乎是否已经加入了这个组播。 复杂的是这一部分网络上接收来的数据的处理。接收端首先必须加入组播中,开设一个监听线程,然后接收数据,并且接收来数据压送到自己的播放GRAPH中。由于对每个客户端来说,组播地址是个可配置的参数,通过引入另一个类,我们把具体的参数转化为对函数的调用结果的依赖,这样提供了足够的灵活性的。 那么如何把数据从Graph中引入到网络中呢,需要自己开发Filter,手动控制数据的流向。在另一端,通过自己开发的接收Filter把数据从网络引入Graph中。 6.2声音的压缩 6.2.1 过滤器类型 开发一个Filter,最首先的是明白它的功能和在Graph中所处的位置。 它处在Graph的最末端,也就是Render过滤器,如果是开始,那么就是Source过滤器。 Filter可以被分成几个大的种类:     1. source filter - filter graph的数据源,这些数据可以来自文件、网络、摄像头或任何其它东西。每一个source filter操纵不同类型的数据源。     2. transform filter - 接收数据,处理数据并将它送入下一个filter。编码filter和解码filter都属于这个种类。     3. Renderer filter - 处于filter链的未端,接受数据并将其展现给用户。比如,一个视频renderer在显示器上绘制视频图像;一个音频renderer将音频数据送入声卡;一个写文件filter(file-writer filter)将数据存盘。     4 splitter filter - 分析输入的数据流并将其分解成两路或多路,比如,AVI splitter分析字节流并将其分解成视频流和音频流。     5 mux filter - 将多路输入流合并成一路。比如,AVI Mux正好与AVI splitter做相反的工作,它将视频和音频流合成为一个AVI格式的字节流。 开发Filter在DIRECTSHOW中比较容易,在使用时可以以组件的方式创建,也可以用传统的类来创建,当然,如果以组件的方式创建的话,对COM编程必须要有一定的了解。通常将组件以一个DLL或者AS的形式进行封装。不管以何种方式进行开发,实现自己的FILTER都需要实现一定的接口。为了使Filter能够成功的添加到Graph当中,并处于适当的位置,起到预定的目的,必须对每个Filter做好详细的设计。 图6.1 Filter之间的连接 当用户要创建自定义的过滤器时,为了在过滤器图表中传送媒体数据,DirectShow过滤器需要支持一些协议传输协议(transport)。相连的过滤器必须支持同样的传输协议,否则不能交换媒体数据。大多数的DirectShow过滤器把媒体数据保存在内存中,并通过PIN把数据提交给其它的过滤器,这种传输称为局部存储器传输(local memory transport)。DirectShow为局部存储器传输定义了两种机制:推模式(push model)和拉模式(pull model)。在推模式中,源过滤器生成数据并提交给下一级过滤器。下一级过滤器被动的接收数据,完成处理后再传送给再下一级过滤器。在拉模式中,源过滤器与一个分析过滤器相连。分析过滤器向源过滤器请求数据后,源过滤器才传送数据以响应请求。推模式使用的是IMemInputPin接口,拉模式使用IAsyncReader接口 。根据实际情况,我们定义过滤器时使用推模式将更加使用和方便。因为数据的产生并不是由自己决定,而是由上级所传递过来,在定位发送和接受过滤器时都需要使用推模式。 6.2.2 选择父类 首先是要选择一个基类,声明自己的类。由基本的FILTER派生出来的类都具有COM特性。从逻辑上来讲,选择一个FILTER基类能有效的节省时间,可以从CBASEFILTER,CBASERENDERER,CBASEVIDEORENDERER,CTRANSINPLACE等中选择,当然,除了CBASEFILTER外,其他的FILTER本身都是从CBasefilter继承而来,每一个在实现父类的虚函数时都添加了一些特定的功能。选择基类的重要一个依据就是FILTER本身所要实现的功能和在GRAPH中所处的位置。 我们所需要的FILTER一个是源,一个尾,考虑到涉及到网络参数的设置,所以接收和发送过滤器均直接继承CBASEFILTER,在PIN的实现中来进一步提供参数设置。 6.2.3 实现Filter 选择一个FILTER后,我们就需要为这个FILTER做点真正的实事了,添加一个真正做事的PIN。同样和FILTER选择基类一样,PIN也需要选择一个合适的基类。在PIN的实现中,需要实现基类所有的纯虚函数,比如CheckMediaType,在该函数内,需要对媒体类型进行检验,以次来让GRAPH按照设定的模式准确的运行。由于之前的设计方案中定下的是使用MP3格式进行传送,这就涉及到音质问题。声音数据在未压缩前的存储和带宽要求是相当吓人,一般来说将达到176000B每秒,这对带宽无疑将是一个重大的消耗,改用MP3格式后能数据尽量压缩到22100左右,这样能在一般的MTU允许下进行正常的数据传送。MP3格式在DIRECTSHOW中有很好的支持,如现成的压缩FILTER和解压缩FILTER。这也是之前采用DIRECTSHOW而非DIRECDSOUND的一个很明显的优势。 PIN之间的连接是通过媒体信息的匹配,而媒体信息的匹配到最低层也就是CMediaType类的匹配,这个类主要提供3个方面的信息:MAJOR TYPE,SUBTYPE和WAVEFORMATEX。前2个是32位的标志符,主要是为某一种类型的数据提供统一的标志,如果是VIDEO类型的话,可能就可以由这2中数据确认而不必查看WAVEFORMATEX了,但某些时候WAVEFORMATEX也是不要的,比如我们这个系统中MP3格式的具体设置,如若缺少,很显然,声音这个GRAPH是连接不起来的,这在实际的编程中也确有深刻的体会。同样的MAJOR,SUBTYPE,不一样的WAVEFORMATEX确会带来截然不同的音质效果。 在得到一个有效的声音数据包后,我们需要给这个包加上一些时间戳,时间戳定义了呈现时间(presentation time),用以让renderer filter确定播放的合适时机。尽管这个可能不是必须的,但是正确的时间戳能确保以后在加入视频后提供可扩展的功能。 6.3数据的发送 发送过滤器处于Graph的最末端,大体上,只需要实现基本的框架并且提供真正的处理核心发送PIN给Graph即可。但是由于它是自定义的过滤器及PIN,在连接时格式设定上有许多需要注意的事情,因为在Directshow中,格式的错误意味着完全的错误,Media type使用AM_MEDIA_TYPE结构体来定义,这个结构体包含了以下内容:     1.Major type:主类型,是一个GUID,定义了数据的整体类型,包括了:视频、音频、未分析的字节流、MIDI等。     2.Subtype:子类型,另一个GUID,进一步定义了数据格式。比如,如果主类型是视频,则子类型可以是RGB-24、RGB-32、UYVY等格式,如果主类型是音频,则可能是PCM或MPEG-1 payload等。子类型提供了比主类型更多的内容,但仍未提供完整的格式定义,比如,子类型没有定义图像尺寸和帧率,这些都将在Format block中被定义。     3.Format block:格式块,定义了具体的格式。格式块是AM_MEDIA_TYPE结构体中一个单独被分配的内存空间,pbFormat成员指向这块内存空间。因为不同的格式会有不同的格式描述,所以pbFormat成员的类型是void*。比如,PCM音频使用WAVEFORMATEX结构体,视频使用不同的结构体包括:VIDEOINFOHEADER和VIDEOINFOHEADER2。formattype成员是一个GUID,指定了格式块包含了哪种结构体,每一种格式的结构体都被分配了GUID。cbFormat成员定义了格式式块的长度。 当格式块被定义时,主类型和子类型包含的信息就显得有点多余了。其实,主类型和子类型为识别格式提供了一个便利的方法,比方说,你可以指定一个普通的24位RGB格式(MEDIASUBTYPE_RGB24),而不需去关心VIDEOINFOHEADER结构体中诸如图像尺寸和帧率这些信息。 typedef struct { WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; WORD wBitsPerSample; WORD cbSize; } WAVEFORMATEX; WAVEFORMATEX中包含一些具体的格式信息,nChannels 用来标志是否双声道,wBitsPerSample指定位大小,nSamplesPerSec指定每秒的采样率。 发送数据的是发送PIN,那么怎么实现呢?原来发送PIN中有个Reciever函数,当上游Pin要向下游发送数据时,就会调用这个函数,并且传递一个只向声音样本数据的指针。通过这个指针我们可以得所要截获的媒体数据。 一旦截获样本,就可以直接发送到网络中,由于声音数据是通过UDP协议传送到组播中,所以可以立即发送,而不需要加入组播。 6.4数据的接收 接收Graph所要做的就是把网络上接收到的数据包发送到过滤器链的最后一个中,但是如何获取数据呢?声音是通过一个一个样本从网络中接收过来的,在接收之前需要加入目的组播,一旦加入后,通过SOCKET监听和接收,就可以获取一个个的样本了。 接受过滤器所需要做的就是把样本注入Graph中,和发送过滤器一样,选择CBaseFilter作为基类,然后再继承实现一个PIN,利用PIN来实现所需要的一系列功能。在这个地方,PIN应该选择CBaseOutputPin作为其父类。在这个PIN中,通过调用DELIVER函数
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 学术论文 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服