1.  引言

在局域网内传输音、视频等多媒体数据主要有两种方案:下载和流式传送。下载的主要缺点是,必须等全部内容传输完毕,然后才能在本地机器打开;而采用流式传输方案,多媒体数据流可以连续、实时地向用户计算机传输,用户不必等到整个文件全部下载完毕,只需在客户端传输开始后经过若干秒的延迟即可进行观看。多媒体数据流的解码播放可使用 DirectShow技术来实现。

2.       DirectShow 技术介绍

DirectShow 是一个Windows 平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。它支持多种多样的媒体文件格式,包括ASF、MPEG、AVI、MP3 和WAV 文件,同时支持使用WDM 驱动或早期的VFW 驱动来进行多媒体流的采集。DirectShow 整合了其它的DirectX 技术,能自动地侦测并使用可利用的音视频硬件加速,也能支持没有硬件加速的系统。

2.1 DirectShow 系统结构

DirectShow 是一套完全基于COM(Component Object Model,组件对象模型的应用系统)。DirectShow 定义了如何利用标准组件来处理流媒体数据,这些组件称为过滤器(Filter )。 DirectShow 使用Filter Gragh 来管理Filter  (管理者叫做Filter Gragh Manager)。Filter Gragh是Filter 的“容器”,而Filter 是Filter Gragh 中的最小功能模块。Filter 一般由一个或多个Pin组成, Filter 之间通过Pin 相互连接,构成一条顺序的链路。 Filter 又可被细分为Source filter (源过滤器)、Transform   filter (变换过滤器)、Renderer   filter   (表现过滤器)等。源过滤器引入数据到过滤器图表中,不同的源过滤器处理不同类型的数据源;变换过滤器的工作是获取输入流,处理数据,并生成输出流;表现过滤器在过滤器图表里处于最后一级,它们接收数据并把数据提交给外设。

将所有过滤器的Filter 通过Pin 连接起来,才可以完成整个任务。DirectShow 的整体结构如下图所示:

图1 DirectShow 系统构架

如图所示,在DirectShow 系统之上是应用程序(Application )。应用程序要按照一定的意图建立起相应的Filter Gragh 。DirectShow 能在Filter Gragh 运行的时候接收到各种事件,并通过消息的方式发送到应用程序,从而实现了应用程序与DirectShow  系统之间的交互。另外,DirectShow 过滤器可以与很多硬件通讯并控制它们,包括当地文件系统,TV 调谐器,视频捕获卡,VFM 编×××,视频显示器(通过DirectShow 和图形设备接口(GDI)),以及声卡(通过 DirectSound) 。这样DirectShow就将应用程序与设备的复杂事物隔离开来。 DirectShow 对于一定格式的文件也提供自带的压缩,解压滤波器。

2.2 DirctShow 的传输机制

DirectShow定义了局部存储传输的两种机制,推模式和拉模式。

推模式中源过滤器产生数据并将它传给下流的过滤器。那个过滤器被动的接受数据,处理它,并进一步将它传给下流。

图2  推模式数据传输流程

在拉模式中,源过滤器连接一个Parser过滤器(分割过滤器,用于把输入流分成多个输出)。Parser过滤器向源过滤器请求数据。源过滤器通过传送数据来相应请求。推模式IMemInputPin接口。拉模式使用IAsyncReader接口。

图3  拉模式数据传输流程

3.  软件的设计与实现

该软件主要涉及到两方面的技术:一是服务器与客户端之间的通信技术,包括多媒体数据的传输、控制命令的传输等,实际应用中使用Windows   Socket 技术来实现;另一方面技术是客户端对接收到的多媒体流实时解码后进行播放,实际应用中采用DirectShow技术完成。

3.1 网络传输

3.1.1传输模式的选择

套接字是支持TCP/IP 协议的网络通信的基本操作单元。根据网络通信的特点,套接字可以分为两类:流式套接字和数据报套接字。流式套接字是面向连接的,提供双向的、有序的、无重复并且无记录边界的数据流服务,它使用于处理大量数据,使用传输控制协议(TCP);数据报套接字是无连接的,支持双向的数据流,但并不保证数据传输的可靠性、有序性和无重复性,使用用户数据报协议(UDP )。

图像信息关键是要连续快速,即使丢上几帧,也不会对操作人员造成太大的影响,同时鉴于本文的设计,考虑到局域网本身的安全机制,以及保证音视频流在局域网内实现组播,采用数据报套接字模式实现。数据报套接字不提供连接,依靠网络自身来保证传输的可靠,不能保证图像不丢失,  但是简单快速。下图是数据报套接字的编程模型:

图4  数据报套接字编程模型

3.1.2数据传输的实现

软件设计了 CListenSocket类用于在服务器端监听客户端计算机的网络连接;CWorkerSocket 类封装了各种Socket 操作,用于实际数据的传送和接收;CMediaSocketServer 类从CWorkerSocket    类派生,用于服务器端数据发送;CMediaSocketClient类从 CWorkerSocket 类派生,用于客户端的数据接收。

在服务器与客户端之间存在通信协议的问题,为了简单起见将控制通信与数据通信合并在一起。在服务器端首先将连续的视音频流分成多块的小包负载数据,并且添加一个信息头一起发送;在客户端根据信息头描述将小包负载数据进行拼装。

以MPEG1 流为例,信息头和负载数据定义如下:

// 信息头

typedef struct

{

unsigned int nMsgType:8;     // 负载类型

unsigned int nDataSize:16; // 数据长度

} MSG_HEADER, *PMSG_HEADER;

// 负载数据

typedef struct

{

CHAR MPEGData[2324];

} MPEG1_PACK, *PMPEG_PACK;

当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这个问题,在程序中我们采用了双缓冲队列技术。双缓冲队列技术即建立两个队列,一个是空闲的缓冲队列PoolList,用来存放接收视频流,另一个是尚未处理的视频流缓冲队列DataList,等待解码。客户端通过socket 接收到数据后,从PoolList 队列的头上取出一个缓冲块,存放数据,并将此块放到DataList 队列的尾部,等待处理。同时,在解码的定时时钟控制下,解码模块从 DataList   队列的头部取出一个缓冲块,读出数据、解码,将读完的缓冲块重新放到PoolList 队列的尾部,循环使用。

3.2  客户端Filter 的设计

客户端通过设计Source Filter 来接收服务器发来的数据,并将数据提供给Filter Graph中其他的Filter 解码,实现音视频流的本地回放,数据传送模式采用的是拉模式。客户端用到的Filter Graph 如下图所示(该图可利用DirectX  自带的软件GraphEdit 获得,并可用于程序的调试):

图5  客户端的Filter Graph

3.3  客户端Filter Graph 的实现

软件设计了CFilterGraph 类来实现Filter Graph 的功能,首先通过BuildGraph 函数创建 一个Filter Graph 组件,然后获得一系列控制接口,然后创建Source Filter,启动等待线程, 在Source Filter 缓存一定数量的数据之后,与Splitter 建立连接,进行视音频数据的传送。

以下是BuildGraph 函数的实现

bool CFilterGraph::BuildGraph(void)

{

m_bInit = false;

// Create filter graph

HRESULT hr = CoCreateInstance(CLSID_FilterGraph,

NULL,

CLSCTX_INPROC,

IID_IGraphBuilder,

(void**)&m_pGB);

//省略获得控制接口部分的代码

if (m_bInit)

{

CMediaType      mt;

mt.majortype = MEDIATYPE_Stream;

mt.subtype    = MEDIASUBTYPE_MPEG1System;

m_pSourceStream     = new CMemStream(m_pDataList);

m_pSourceReader     = new CMemReader(m_pSourceStream, &mt, &hr);

m_pSourceReader->AddRef();

// Add our filter

hr = m_pGB->AddFilter(m_pSourceReader, NULL);

if (FAILED(hr))

{

m_bInit = false;

}

}

if (m_bInit)

{

// Waiting for event to start filter graph

::AfxBeginThread((AFX_THREADPROC)CFilterGraph::WaitingThrd, this);

}

return m_bInit;

}

等待线程的执行函数体:

UINT CFilterGraph::WaitingThrd(void * pParam)

{

CFilterGraph * pGraph = (CFilterGraph *) pParam;

if (pGraph != NULL && pGraph->m_pDataList != NULL)

{

::WaitForSingleObject(pGraph->m_pDataList->m_hBufEnough, INFINITE);

if (!pGraph->IsRunning())

{

pGraph->StartGraph();

}

}

return 1;

}

4.    结束语

基于COM组件的DirectShow 由于其广泛的适用性和可移植性,正日益受到重视和得到了广泛的应用。本文介绍了DirectShow基本结构、组件和机制,使用Socket通信机制,编程实现在局域内音视频流信息的多机共享,后续工作将初步实现局域网内的视频点播功能。

转载于:https://blog.51cto.com/rosehacker/1563406

基于DirectShow的局域网内音视频流的多机共享相关推荐

  1. 如何在局域网内搭建FTP服务器,实现信息共享

    如何在局域网内搭建FTP服务器,实现信息共享 首先打开控制面板,点击程序 点击程序,点击启用或关闭windows功能,找到lnternet lnformation Services 点击前面小&quo ...

  2. 项目实战:基于 TCP 的局域网内高性能文件传输系统设计与实现

    本项目开发基于 Red Hat Enterprise Linux(RHEL) 6.3 平台 ,通过本项目大家会深入理解下述内容: Socket 网络编程技术 基于TCP/IP 协议的网络编程技术 基于 ...

  3. 基于SMBJ在局域网内读取共享文件

    近期在做公司项目时,有个工作站文件.数据采集的功能需求,文件会被存储在局域网内某台电脑的data/{yyyyMMdd}/...文件夹下,yyyyMMdd代表当天的日期,百度查了下,通常有两种方式可以实 ...

  4. 基于VC++的局域网内主机监控系统设计与实现

    局域网内主机监控系统 目录 引言 2 1.1 编写目的 2 1.2 项目背景 2 1.3 课题内容和要求 3 1.4 名词解释 4 参考文献 4 需求分析 5 2.1 现有系统概述 5 2.2 对新系 ...

  5. 2021-08-03 在ubuntu 18.04上创建基于VNC的局域网内远程工作环境

    目录标题 1. 场景描述 2. 环境搭建概要 2.1 工作站 2.2 客户端 2.3 远程登陆 3. 问题说明 3.1 单用户支持 3.2 客户端显示不全 3.3 VNC vs. Teamviewer ...

  6. 如何访问局域网内宿主机上的虚机服务

    问题 最近在验证网关及数据库切换方案,由于测试环境机器都在使用,于是在局域网内的一个windows机器上通过WMware虚拟出服务器来实现的,但是虚拟机上完成网关及数据库的搭建后,发现在局域网内无法访 ...

  7. 基于WFP等网络驱动实现局域网内所有设备通过代理上网

    by fanxiushu 2020-10-13 转载或引用请注明原始作者 开始之前,我们先来理解标题是什么意思. 这里所说的局域网内的所有设备通过代理上网,并不是在每台设备上安装某个代理软件然后再通过 ...

  8. 同一网段计算机无法共享打印机,Win7同一个局域网内共享打印机不成功的修复方法...

    打印机共享需要在同一个局域网内完成,这样打印机可以共享多台电脑.一位用户说自己的打印机和台式Win7系统电脑的连接已经成功,但就是没办法打印机文件,怎么回事呢?win7系统共享打印机的前提是需要关闭杀 ...

  9. 同一个局域网怎么计算机共享打印机,Win7同一个局域网内共享打印机不成功的修复方法...

    打印机共享需要在同一个局域网内完成,这样打印机可以共享多台电脑.一位用户说自己的打印机和台式Win7系统电脑的连接已经成功,但就是没办法打印机文件,怎么回事呢?win7系统共享打印机的前提是需要关闭杀 ...

最新文章

  1. linux内核tor03,Linux内核x86架构引导协议4(翻译)
  2. view是怎么被展示在手机上的?
  3. 【java】map的几种遍历方式
  4. QT的QAudioDeviceInfo类的使用
  5. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
  6. AMTEmu v0.9.2
  7. Latex特殊符号大全(高清)
  8. linux生成可执行文件的过程
  9. 奥运期间证券期货业网络与信息安全突发事件应急预案(一)
  10. 腾讯云 DDNS 方案
  11. python列联表分析
  12. java基于Springboot+vue的球鞋销售商城网站 elementui
  13. 微服务 弹性伸缩_如何构建弹性微服务
  14. 【JavaWeb】之MVC三层架构
  15. 【数据结构】 栈的知识点
  16. 高权重网站外链如何建设和打造?
  17. SRILM文档分析之Prob.h
  18. 写两个函数 分别求两个整数的最大公约数和最小公倍数 用主函数调用这两个函数 并输出结果 两个整数由键盘输入
  19. redis事件通知(notify-keyspace-events Ex)
  20. 基于uni-app开发的一款视频播放器插件

热门文章

  1. Vue.js(17)之 插槽
  2. GitLab-CI与GitLab-Runner
  3. vue源码学习--vue源码学习入门
  4. u-boot分析(四)---设置异常向量表|设置SVC模式
  5. .net 下语音合成
  6. Windows消息机制详解-6
  7. 模态对话框和非模态对话框的消息循环分析
  8. CyAPI.lib(CyAPI.obj) : error LNK2019: 无法解析的外部符号...
  9. uniapp底部弹出框效果
  10. 电子病历模板_年会献礼3:浮针专家平台病历撰写系统年会启动