基于Directshow的H.264流媒体播放器设计

2023-11-12

0引言

  DirectsHow应用框架完成了流媒体处理的底层工作,使得编程者无需关心数据如何输入,以及处理完后如何输出,而只需关心如何对输入数据进行处理。H.264视频编解码标准具有高压缩比和优良的网络亲和性,被普遍认为是最有影响力的流媒体视频压缩标准。将Direct-show和H.264两种相结合的流媒体播放器无疑将具有非常优秀的性能。

  1Directshow技术和H.264视频压缩标准简介

  Directshow是微软公司提供的一套流媒体开发软件包,为在windows平台上处理各种格式的媒体文件的回放、音视频采集的高性能要求的多媒体应用,提供了完整的解决方案。

  Directshow是一套完全基于COM的应用系统,该系统位于应用层中,它使用FilterGraph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫Filter;各个Filter在FilterGraph中按照一定的顺序连接成一条“流水线”协同工作。Filter是一个COM组件,其功能可以由用户自行实现,DirectShowSDK也为用户提供了一些标准的Filter供用户使用。各个Filter在FilterGraph中按一定顺序通过Pin互相连接起来,Pin也是一个COM对象。

  H.264是由ITU-T和ISO/IEC的联合开发组共同开发的最新国际视频编码标准。H.264/AVC视频编码标准在编码质量和压缩比上比原有的视频编码标准都有了明显的提高。在相同的视觉感知质量上,编码效率比H.263,MPEG-2和MPEG-4提高了50%左右。H.264不仅具有优异的压缩性能,而且具有良好的网络亲和性。因此,H.264被普遍认为是最有影响力的流媒体视频压缩标准。

  2系统设计框架

  本系统基于Direotshow应用框架和H.264视频压缩标准,实现了从网络接收流媒体数据,并在客户端实时播放的功能。流媒体文件是采用H.264编码的AVI文件,由于directshow提供了AVISplitteRFilter、AudioDecoder和标准的Video/AudioRenderer,因此,本系统只需设计自定义的网络源Filter、H.264解码Filter。

  多媒体流式传输实际上牵涉到两个方面的技术。其一就是服务器与客户端的通信技术,包括多媒体数据的传输、命令控制等;其二就是客户端对接收到的多媒体流实时解码后播放的技术。显然,网络通信可以使用windowssocket技术,多媒体流的解码播放可以使用direct-show技术。本文采用direetshow应用框架,设计了网络源filter和h.264解码filter,并通过FilterGraph构建了流媒体播放器。

  播放本地基于H.264编码的AVI文件的FilterGraph如图1。只需将本地FileSourceFilter替换为网络源Filter,将CoreAVCVideoDe-coder替换为h.264解码Filter,即可实现网络H.264视频播放器。

  

播放本地基于H

 

  3系统的设计与实现

  3.1Filter设计流程

  Filter的编码实现包括Filter的注册信息、Filter上的框架函数实现、逻辑控制类实现、自定义接口实现、属性页实现、产权保护等。

  首先,要对Filter所要完成的功能和它在FilterGraph中的位置进行分析,以确定filter模型,选择一个合适的基类;然后,再定义输入输出PIN以及自定义接口,注册Filter信息;最后实现基类的全部纯虚函数和自定义接口函数,并重写基类的相关函数以定制filter功能。

  3.2网络源Filter的设计

  源Filter主要功能是接收服务器发来的流媒体数据,并提供给FilterGraph中其它Filter使用。

  由于directshow自带的AVIsplitter工作于拉模式,故该源Filter也工作于拉模式。

  本源Filter采用双缓冲循环队列技术来实现数据的接收和向下一级Filter传递数据。采用该技术有如下理由:

  (1)在SourceFilter与SpliRer连接的过程中,会从SourceFilter中读取一部分数据,以获得数据的格式描述,否则FilterGraph无法完成连接。源Filter与SplitterFilter进行连接前,应启动一个等待线程,当SourceFilter的数据缓存预先接收到足够的数据后,再构建完整的FilterGraph。

  (2)当完整的FilterGrapH构建完成,并且处于运行状态后,SourceFilter必须动态地接收数据,并持续地把新数据提供给SplitteRFilter,双缓冲循环队列既充分利用内存空间,又能为SplitterFilter提供稳定的数据源。

  (3)缓冲队列可以稳定码率,有效减小网络延时、阻塞和抖动的影响。

  源Filter的工作过程如下:建立一个循环缓冲队列,队列尾指针用于缓冲从网络接收的数据,队列头指针供Splitter读取数据,进行音视频分离,并传给下一级Decoder处理;当Socket接收到网络数据后,将数据插入队列尾部,并使尾指针后移;当Splitter需要读取数据时,从队列头读取数据,并使头指针后移。

  流媒体传输采用客户端/服务器的架构,服务器与客户端之间还有一个Socket通信协议问题,由于流媒体是连续的,它的同步点不能随意选择,因此,为了传送流媒体数据,必须使用面向连接的可靠的传输协议(TCP)。客户端与服务器端的控制与反馈消息,则可以使用(UDP)来传输。服务器端首先创建一个侦听Socket,侦听来自客户端的连接请求。一旦侦听到客户端的请求,服务器端就创建一个用于数据传送的Socket,并绑定到请求连接的客户端,此时,服务器处于数据传送的就绪状态。当客户端发出命令,服务器再根据命令的类型执行相应的操作,如数据发送、停止、断开连接等。

  在服务器端首先将连续的H.264流分成一块一块小包的负载数据,并且加上一个信息头一起使用TCP协议发送;在客户端根据信息头描述,将小包的负载数据进行拼装,然后进行H.264的解码播放。Socket数据传送结构为:负载类型(8bit)、负载数据长度(16bit)和负载数据包(2324Byte)。

  客户端的实现可以参考SDK中的MEMFileFilter,直接从SDK例子将asyncrdr.cpp、asyncrdr.h、asyncio.cpp、asyneio.h四个文件拷贝过来,然后在MemFilter.h文件中从CAsyncStream派生流处理类CMemStream,定制数据源并进行数据的读取操作;从CAsyncReader派生滤波器类CMemReader,实现含1个输出PIN的SourceFilter框架,完成与SplitterFilter的连接。

  网络源滤波器类间数据流程如图2,下一级Filter“拉”线程数据流程如图3。其中:CAsyneStream用以标示数据流;CAsyneRequest标示输入与输出请求;CAsyncIo实现数据输入和输出的控制。编程主要实现CMemStream:Read()函数以实现从特定的数据源读取数据到下一级Filter的Sample中。

  

线程数据流程

3.3H.264解码Filter的设计

 

  该滤波器工作于Splitter和Rendererfilter之间,包含一个输入和一个输出,且输入和输出pin上的媒体类型不一致,故选择CTrans-formFilter作为基类,派生子类CX264Decode。

  ffmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案。利用ffmpeg中的Libavformat和libavcodec库访问大多数视频文件格式是一个很好的方法。将ffmpeg中关于h.264解码的操作封装为C++类,供H.264解码Filter调用以实现解码功能。

  子类CX264Decode必须要实现的纯虚函数有:CheckInputType()实现输入Pin上的媒体类型检查;CheckTransform()检查是否支持从该输入pin到输出pin的变换操作;DecideBufferSize()决定Samlple内存的大小;GetMediaType():提供输出Pin上的首选媒体类型;Transform():实现解码变换。

  子类CX264Decode可选的重写虚函数有:初始化和反初始化流:StartStreaming()和StopStreaming();响应质量通告消息:AlterQuali-ty();获取媒体类型被实际设置的时间:SetMediaType();连接时获取额外的接口:CheckConnect()、BreakConnect()和CompleteConneet();定制变换过程:Receive();标准化设置输出Sample:InitializeOutputSample()。

  本Filter设计主要流程如下:

  (1)Filter注册信息

  定义类工厂模板,填写Filter的注册信息;同时实现DLL文件所必须实现的注册和反注册函数:DLLRegisterServer和DLLUnregisterSe-rver。

  (2)框架函数的实现

  实现函数CreateInstanee,用于创建Filter对象实例;实现函数CheeklnputType,用于对输入Pin上的媒体类型检查;实现函数Transfo-rm,用于H.264的解码操作;实现函数NonDelegafingQueryIntefface,用于暴露Filter支持的自定义接口,使应用程序可以设置解码器的参数;实现函数CompleteConnect,可以在输入Pin成功连接后取得媒体类型描述,并将输入数据的格式设置给应用逻辑控制对象;实现函数St-artStreaming和StopStreaming,可以分别调用应用控制逻辑对象的相应函数,进行流处理的初始化和反初始化操作。

  (3)逻辑控制类的实现

  逻辑控制类是本Filter设计的核心,框架函数和自定义接口函数的相关操作都是委托给逻辑控制类来实现的。该类实现了H.264.的解码参数的设置与解码操作,主要调用封装了H.264解码的C++类来实现。

  利用ffmpeg库进行H.264解码时,需要自定义两个关键函数:open_net_file()和read_buffer_frame()。其中,open_net_file()函数完成与流媒体服务器的连接,接收指定流媒体文件的流相关信息,并返回类型为AVFormatContext结构体的值。read_buffer_frame()函数从bu-ffer缓冲中读取一帧数据,并交由库函数avcodec_decode_video()解码。

  (4)自定义接口的实现

  将Filter类从自定义接口类派生,并声明自定义接口的所有接口方法;然后在Filter类的实现文件中实现这些接口法,其实大都是调用应用逻辑控制类的相应函数;最后在函数NonDelegatingQueryInteRFace中暴露我们的自定义接口。

  3.4播放器的设计

  播放器采用DirectsHow应用框架,采取界面、控制逻辑和数据分离的三层程序设计方法。界面类直接从标准的对话框类CDialog派生,在界面类中定义两个自定义类:数据封装类和逻辑控制类。界面类表达一种用户操作逻辑;数据封装类集中管理各种参数;逻辑控制类具体实现业务应用逻辑。采取Directshow应用框架,不必关心数据如何输入和输出,这些问题都由Filter框架负责,只需更多的关注数据处理的算法实现、效率优化等问题。采取界面、控制逻辑和数据分离的设计结构,不仅使程序框架清晰、容易被人理解,而且具有良好的移植性和扩展性。

  播放器基于FilterGraphManager构建包含网络源Filter和H.264解码Filter的FilterGraph,即可实现网络流媒体的播放。界面类实现视频显示界面与用户的操作交互,控制逻辑可以控制视频的播放、暂停、停止、解码参数设置等,数据类实现对数据的操作管理。

  4结束语

  本流媒体播放器系统采用了Directshow应用框架和H.264视频编解码标准,能很好的实现网络流媒体视频的播放,具有结构清晰、良好的可扩展性与可移植性。由于WINCE系统是微软提供的嵌入式实时操作系统,提供了对Directshow的应用支持,故本系统也可以很好的移植到win-ce的嵌入式应用平台,实现嵌入式端的流媒体视频播放。同时,本流媒体播放系统也可很好地移植到视频点播系统中,因其采用高压缩比、低码率的H.264视频编解码标准。能有效减少网络负载、减小带宽,从而减轻网络对流媒体传输中所存在的丢包、抖动、延时等影响。

 

转自:http://www.elecfans.com/video/audio/20110311190003.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于Directshow的H.264流媒体播放器设计 的相关文章

  • Primefaces 中的过滤数据表仅有效一次

    我正在尝试使用 Primefaces 过滤数据表 就像这个例子 http www primefaces org showcase ui datatableFiltering jsf 在网络浏览器中 我输入要过滤的文本 它会工作一次 但是当我
  • 使用组合框过滤文本框

    好吧 我必须创建一个表单 它获取文件夹的内容并将其列出在文本框中 是的 文本框不是列表框 然后 我必须使用包含文件夹所有扩展名的组合框来过滤此文本框 例如 如果我在组合框中选择 txt 则文本框应过滤以仅显示所有文本文件 除了让组合框过滤文
  • 如何为高流量网络应用程序实现“保存搜索”功能?

    我想知道可以在 eBay 等大型网络应用程序上找到的 保存的搜索 功能 您可以做的就是保存搜索 例如 宾得镜头 50mm 1 4 每当有人出售符合搜索条件的新优质标准快速宾得镜头时 您都会收到通知 对我来说 实现此类功能并不是一件简单的事情
  • SQLAlchemy - 将文本查询与过滤器结合起来

    我在用着SA 0 6 6 Python 2 66 and Postgres 8 3 我有某些查询需要一些复杂的安全检查 可以使用WITH RECURSIVE询问 我想做的是将文本查询与查询对象结合起来 这样我就可以根据需要应用过滤器 我最初
  • JS中如何过滤多个字符串? [复制]

    这个问题在这里已经有答案了 我希望能够过滤数组中的多个字符串 类型 例如我想过滤类型meat并输入fruit在下面的数据结构中 我想要实现的是过滤数据对象 const data type meat food hamburger type f
  • H264 字节流到图像文件

    第一次来这里所以要温柔 我已经在给定的 H 264 字节流上工作了几个星期 一般注意事项 字节流不是来自文件 它是从外部源实时提供给我的 字节流使用 Android 的媒体编解码器进行编码 当将流写入扩展名为 H264的文件时 VLC能够正
  • 如何从数据框中删除少于 5 个观察值的个体 [重复]

    这个问题在这里已经有答案了 为了澄清这个问题 我将简要描述数据 中的每一行data frame是一个观察值 列代表与该观察值相关的变量 包括 观察到什么个体 观察时间 观察地点等 我想排除 过滤观察值少于 5 个的个体 换句话说 如果 in
  • h264 参考帧

    我正在寻找一种在 h264 流中查找参考帧的算法 我在不同的解决方案中看到的最常见的方法是查找访问单元分隔符和 IDR 类型的 NAL 不幸的是 我检查的大多数流没有 IDR 类型的 NAL 我将不胜感激的帮助 问候 雅采克 H264 帧由
  • Grails:如何在过滤器中使用createLink?

    简短的问题 我该如何使用创建链接 http grails org doc latest ref Tags createLink html createLink在过滤器中 我收到错误 无方法签名 MyFilters createLink 适用
  • 如何从另一个数组值中过滤数组值并返回新数组? [复制]

    这个问题在这里已经有答案了 我有两个数组 all languages and taken languages 第一个包含所有语言 例如 200 种或其他语言 第二个包含之前选择的语言 从 0 到 200 种 我需要删除所有已采用的语言 ta
  • 在 MediaFoundation 硬件 MFT 中设置更大的 GOP 大小

    我正在尝试直播通过桌面复制 API 捕获的桌面 H264 编码工作正常 除了桌面复制 API 仅在屏幕发生变化时才传送帧 但视频编码器希望以恒定的帧速率传送帧 因此 当没有触发屏幕更改时 我被迫保存之前的样本 以恒定的速率向编码器提供数据
  • 在 MongoDB Java 驱动程序中如何使用 $filter

    我有一个适用于 MQL 的查询 我需要将其翻译成Java MQL 中的查询如下所示 db
  • Android 的互补滤波器(陀螺仪 + 加速器)

    最近我做了一些研究 使用加速度计 陀螺仪来使用这些传感器来跟踪智能手机 而无需 GPS 的帮助 请参阅这篇文章 基于陀螺仪和加速度计的室内定位系统 https stackoverflow com questions 7499959 indo
  • Android SQLite 数据库从查询中删除重复项

    我是 SQLite 新手 我使用此查询是为了从特定用户的列中提取所有行 Cursor c db query true TABLE COLUMN USER user null null null null null 这是表格的示例 group
  • 多个组合框绑定到一个公共源,强制执行不同的选择

    我正在尝试将多个 ComboBox 绑定到一个公共源集合 并强制执行一旦进行 ComboBox 选择 该所选项目就有可能从其他 ComboBox 中删除 该集合是动态构建的 因此我是用代码来完成的 到目前为止 我已经尝试以多种方式实现这一点
  • 如何在 Matlab 中对数组应用低通或高通滤波器?

    有没有一种简单的方法可以将低通或高通滤波器应用于 MATLAB 中的数组 我对 MATLAB 的强大功能 或数学的复杂性 有点不知所措 需要一个简单的函数或一些指导 因为我无法从文档或网络搜索中找到答案 看着那 这filter http w
  • 在 Django 中使用下拉表单过滤 ListView 的最佳方法

    我正在尝试使用下拉表单根据用户过滤 ListView 模型 py class Post models Model author models ForeignKey auth User verbose name Post Author vie
  • 如何过滤视图两列 OR 而不是 AND?

    在 Google 表格中 我想过滤查看结果 以便仅显示 D 列和 或 E 列中带有 x 的行 如果我过滤以显示其中包含 x 的列 则它将仅显示 D 列和 E 列中包含 x 的行 我如何让它做 和 或 操作 当我单击列中的过滤器按钮时 它只会
  • RegisterGlobalFilters 的目的是什么?

    在 MVC3 中 我以这种方式启用了 CustomErrors
  • 推荐用于视频编码的最佳质量/性能 H264 编码器?

    我正在寻找一种速度快 需要较少 CPU 功率并生成质量非常好的 mp4 视频的视频编码器 输入视频可以是任何格式并由用户上传 我唯一知道的是 FFMPEG 库 还有其他更好的吗 该程序必须有一个我感兴趣的批处理实用程序 exe 如果您愿意分

随机推荐

  • Element之el-switch上显示文字

    如果我们想要在Element组件库中的switch开关组件上显示文字该怎么做 1 Html部分
  • pclint html报告,PC-lint 9 + 中文手册

    实例简介 PCLINT是一种代码检查工具 还包括中文文档 实例截图 核心代码 Pc Lint9 pclint autorun inf DOS ins choose16 exe choose exe install exe lint exe
  • ACE_Message_Block例子

    include ace OS h include ace Message Block h include ace FILE IO h include
  • 【Absible学习】Ansible常用模块---包管理模块

    yum repository模块 yum repository模块可以管理远程主机上的yum仓库 模块参数 参数 说明 name 必须参数 用于指定要操作的唯一的仓库ID 也就是 repo 配置文件中每个仓库对应的 中括号 内的仓库ID b
  • 深度学习--手写数字识别<一>

    手写字符识别数据集THE MNIST DATABASE of handwritten digits http yann lecun com exdb mnist 其中训练集60000例 测试集10000例 加载数据 1 读取数据 usr b
  • 博客营销分析:博客营销的优势+方法技巧+成功案例介绍

    博客营销分析 博客营销的优势 方法技巧 成功案例介绍 一 博客营销是什么 博客营销的定义 首先 先为大家介绍博客的定义 博客是一个可以发布文字 链接 图片 视频的网站 是实现信息分享与交流的平台 而博客营销是博主通过博客内容向网站用户传递信
  • [整理]MySQL8-安装、启动、卸载、初始密码、忘记密码(CentOS,Ubuntu,Widows)

    系统和MySQL更新换代都很快 我用到时会顺手整理在这里 内容没什么技术含量 也不保障内容的全和新 每次遇到问题网上搜索一下很容易找到解决方法的 我工作电脑用Widows Ubuntu WSL 服务器用CentOS 所以三个系统都安装过 C
  • 【Python】字典内容写入json文件

    Python中有序字典和无序字典 一键多值字典 Python将字典内容写入json文件 1 无序字典 目前了解三种 在Python中直接默认的是无序字典 这种不会按照你插入的顺序排序 即使你对字典排序后 返回的也是一个list变量 而不是字
  • echarts的图表双击事件、单击某块、滚轮放大缩小

    echarts的图表双击事件 dblclick
  • 华为机试:HJ2 计算某字符出现次数

    描述 写出一个程序 接受一个由字母 数字和空格组成的字符串 和一个字符 然后输出输入字符串中该字符的出现次数 不区分大小写字母 数据范围 1 le n le 1000 1 n 1000 输入描述 第一行输入一个由字母和数字以及空格组成的字符
  • Android 源码分析 - 系统 - Settings

    core 源代码 core java android provider Settings java 定义一系列配置项名称 索引 常量 SettingsProvider apk 源代码位于 frameworks base packages S
  • 【Vuex入门】——(四)Mutation

    一 Mutation的作用 更改 Vuex 的store 中的状态的唯一方法是提交 mutation Vuex 中的 mutation 非常类似于事件 每个 mutation 都有一个字符串的 事件类型 type 和 一个 回调函数 han
  • Python语言程序设计 习题6

    一 选择题 1 下列Python数据中其元素可以改变的是 A A 列表 B 元组 C 字符串 D 数组 2 表达式 2 in 1 2 3 4 的值是 D A Yes B No C True D False print 2 in 1 2 3
  • python是什么意思中文、好学吗-零基础学python难吗?好学吗?

    Python是一种什么语言 Python是一种计算机程序设计语言 你可能已经听说过很多种流行的编程语言 比如非常难学的C语言 非常流行的Java语言 适合初学者的Basic语言 适合网页编程的JavaScript语言等 Python是他们其
  • 如何使用下标遍历二维数组

    点击打开链接 int my 2d array 10 10 假定数组my 2d array 已经预先被填充了数据 int i j 遍历这个数组 for i 0 i lt 10 i 向下遍历各行 for j 0 j lt 10 j 穿越各列 p
  • Python:Unused import statement 解决方法

    Python 学习 21052501 1 Unused import statement 解决方法 Pycharm file 菜单下有Invalidate caches Restart菜单栏 点击清除缓存重新启动Pycharm即可 2 In
  • 反思深度学习与传统计算机视觉的关系

    来源 算法与数学之美 某种程度上 深度学习最大的优势就是自动创建没有人会想到的特性能力 如今 深度学习在众多领域都有一席之地 尤其是在计算机视觉领域 尽管许多人都为之深深着迷 然而 深网就相当于一个黑盒子 我们大多数人 甚至是该领域接受过培
  • 【C++进阶】二叉搜索树递归与非递归的模拟实现(附源码)

    一 什么是二叉搜索树 二叉搜索树又称二叉排序树 它或者是一棵空树 或者是具有以下性质的二叉树 根据二叉搜索树的性质 它的中序遍历结果就是一个升序列 二 二叉搜索树的模拟实现 节点 Node 在实现二叉搜索树之前 要先定义一个节点 成员变量包
  • Shiro权限框架-在线并发登录人数控制(9)

    1 实现原理 在实际开发中 我们可能会遇到这样的需求 一个账号只允许同时一个在线 当账号在其他地方登陆的时候 会踢出前面登陆的账号 那我们怎么实现 自定义过滤器 继承AccessControlFilter 使用redis队列控制账号在线数目
  • 基于Directshow的H.264流媒体播放器设计

    0引言 DirectsHow应用框架完成了流媒体处理的底层工作 使得编程者无需关心数据如何输入 以及处理完后如何输出 而只需关心如何对输入数据进行处理 H 264视频编解码标准具有高压缩比和优良的网络亲和性 被普遍认为是最有影响力的流媒体视