• 用Directshow进行电视卡的音视频信号采集和SDI信号输出


    本来我并非多媒体软件工程师,但因为项目需要一时也找不到其他人,只好自己顶上去,到昨天为止,项目基本上算是功能都实现了。我个人的习惯是每经历过一次开发,就要总结一次,主要是技术总结。

    参考资料都来自于陆老师的《Directshow编程指南》和google搜索。

    1. Directshow开发环境的搭建

    对于VS2005,VS2003及VC6的开发环境,必须具备

      DirectX SDK    :  包含了ddraw.h和一些runtime)

      dxsdk extras   : 包含了strmiids.lib,quartz.lib和一些视音频的头文件,包括DVD的定义,复合视频的定义等等

          然后你还需要一个BaseClasses,提供strmbase.lib(调试版本为strmbasd.lib)

    对于VS2008,安装时自动包含了Microsoft SDK里面包含了ddraw.h及extras里面的一些内容,只需要BaseClasses即可,我把BaseClasses打个包,放在这里,方便大家使用。

    2. DirectShow程序的部署

    我用的VS2008开发,因此在部署到其他未安装开发环境的机器上,必须要先下载vcredist_x86.exe(我的是x86平台)。

    在VS2008中选择release版本进行生成,此处千万要注意DirectShow应用程序一定要引用strmbase.lib,而不是strmbasd.lib,因为strmbasd.lib必然依赖于调试库,而vcredist_x86.exe则不带调试库支持

    此外为了获取strmbase.lib,你必须要用和应用程序相同的VS版本来编译BaseClasses。

    我犯的第一个错误是:用VS2008编译BaseClasses生成strmbase.lib和strmbasd.lib,用VS2005编译我的应用程序得到.exe,结果部署到其他机器时出错

    我犯的第二个错误是:用VS2008编译BaseClasses生成strmbase.lib和strmbasd.lib,用VS2008编译我的应用程序得到.exe,但是引用了strmbasd.lib,结果部署到其他机器时出错

    3. 关于DirectShow的Pin查找

    一般的DirectShow程序开发,都要用到GraphEdit这个程序,将一系列的filter拖进工作区,然后一个一个连起来,形成一个完整的从输入到输出的数据流链条。

    在使用GraphEdit验证你的思路正确之后,你就得在程序中来逐渐实现这个链条。其中我总结几点经验:

    1) 在GraphEdit中实现的连接图一定能用程序实现

    2)在GraphEdit中使用智能链接生成的图可能不是最简单的链接

    3)在GraphEdit中,一个filter引脚的名字是”ABC“,如果你在程序中创建一个Filter,然后调用FindPin函数去找这个Pin不一定能找得到,更为奇特的是,你用EnumPins方法去枚举这个Filter上的Pins,却又能真正找到具有这个名字的Pin。我在CSDN上发现很多人也都碰到过这个问题。这个应该是Filter的编写者不负责任的一种做法。后来我偶然之间发现可以通过序号去找到Pin。代码如下:

    IBaseFilter *pCapture =  //创建一个FilterIPin* outPin = NULL;1: hr = pCapture->FindPin(L"Capture", &outPin);2: hr = pCapture->FindPin(L"1", &outPin);

    Line1是根据名称去查找,如果失败,则可采用序号去查找。这个序号是字符串,可以是0, 1, 2, 3等,你可以逐个尝试,直到找到你要的Pin。

    4) 在GraphEdit中,如果两个Filter之间的Pin无法连接,你别以为你的思路走不通了。这个时候你应该仔细查看Pin的Properties,注意是Pin的属性,不是Filter的属性。在Pin的属性中修改一下输出视频的格式,压缩方式,分辨率,说不定就能连上了。

    在程序中,我们通过IAMStreamConfig这个接口来进行输出流格式的设置。代码请参考陆老师的书。

    5) 常用的几种参数设置和控制接口:

        IAMStreamConfig: 设置某个Caputre型的Filter的音视频输出格式

        IAMCrossbar: 设置电视卡的输入源,比如可以来自电视信号,SVideo或者复合AV等

        IVideoWindow: 设置视频显示的窗口,窗口大小,显示风格等

        IMediaControl: 控制媒体的播放,停止,暂停等

        IAMAudioInputMixer: 选择音频采集数据源,可以有CD,麦克风,线路输入,立体声等输入

    6) 一般电视卡都是带有音频输出的,你直接插上耳机就可以听得到声音。可有的时候我们想对这些声音做一些处理,比如通过另外一个通道输出到其它设备,或者是写入到文件等等。在我的项目中,就需要把音频信号通过SDI通道进行输出。此时我们必须先把音频信号采集进来,然后再输出。一般的声卡都能做采集工作,只要带有Line In接口或者麦克风接口都可以。采集的第一步是把电视卡的音频输出用硬线连接到声卡的Line In,然后在程序中创建声卡采集的Filter,在Filter上获得IAMAudioInputMixer接口,并用该接口选择音频输入源为Line In,然后把Capture端连接到其他的音频输入通道。一般不采用Mic作为采集接口,因为Mic阻抗大,噪声很高,Line In相对而言质量更加好一点。

    选择音频输入源的代码如下:

    Code

    用DirectShow编程,最大的困惑就是不知道什么功能通过什么接口来实现,这个需要去搜索或者去查资料书。等有一定经验之后,难点就转向了视频格式的匹配、各种特定硬件编写的filter的使用,如果越学越深入,那么难点就转向了如何写健壮的各种filter等。

    我无意在DirectShow的路上走下去,只是依循自己的习惯,简单地总结了下这一小段开发经历,如果能给大家提供帮助,那就是意外之喜了。

    hyruur@163.com

  • 相关阅读:
    scala 数据结构(七 ):集 Set
    scala 数据结构(六):映射 Map
    scala 数据结构(五):队列 Queue
    scala 数据结构(四):列表 List
    scala 数据结构(三):元组Tuple
    scala 数据结构(二):数组
    scala 数据结构(一):数据结构简介
    Scala 面向对象(十三):隐式转换和隐式参数
    vba报表制作
    Apache与Nginx
  • 原文地址:https://www.cnblogs.com/hyruur/p/1525465.html
Copyright © 2020-2023  润新知