您好, 访客   登录/注册

基于H.264的可复用视频播放框架设计

来源:用户上传      作者: 王国清

  摘 要通过分层框架设计,基于H.264视频流从播放展现、播放控制、视频解码、视频流解析的分层结构,实现可复用的视频播放框架,为各种车载视频监控产品提供一致的H.264视频播放效果和体验。
  【关键词】可复用 视频 H.264 框架 YUV
  1 引言
  近几年,随着3G/4G移动通信技术的普及,加之国家对道路运输车辆监管力度的不断加大,车载视频监控技术得以快速普及。而目前市面上车载视频监控产品种类繁多,虽然主要都是基于H.264编码,但是视频参数、封装格式五花八门,厂商提供的视频播放软件功能和效果也良莠不齐,导致运营商在各种视频播放软件中来回切换,影响用户体验和管理效率。因此,有必要设计一套可复用的视频播放框架,通过支持简单的二次开发屏蔽产品差异,提供一致的用户视频播放体验。
  1.1 H.264
  H.264是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准,是目前主流的视频压缩标准。
  1.2 YUV
  YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),主要用于优化彩色视频信号的传输。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽。
  2 框架设计
  对H.264压缩标准而言,摒弃不同容器、不同传输方式的封装差异,视频的播放实际就是H.264流的解析和播放。因此,完全可以设计一套基于H.264的通用视频播放框架,实现H.264视频流从数据流解析到播放展现整个流程。基于这套框架,各厂商只需针对不同的车载监控产品开发对应的解析模块完成H.264流的提取,便可完成不同车载视频监控产品的无缝接入,提供完全一致的播放效果和体验。
  整个框架设计上主要分为:展现层、播放控制层、视频解码层、视频流解析层四部分。其中,视频流解析层提供了供二次开发的解析模块适配接口,以及一系列厂商开发的用于对接不同车载终端产品的解析模块。
  2.1 展现层
  展现层是整个播放框架的用户UI层,主要处理的对象是从播放控制层获取到的下一帧YUV图像。其功能主要有:YUV图像播放、播放控制UI界面和附加辅助功能及菜单。
  (1)YUV图像播放包含一个播放窗口和一个定时刷新线程。播放窗口用于展现视频画面。定时刷新线程按照基于帧率计算的时间周期(1000毫秒/帧率)间隔,定时获取下一个YUV视频图像并在播放窗口中进行渲染播放。目前可选的视频画面渲染框架有很多,如SDL、D3D、DirectShow等,都是较为成熟的多媒体框架。
  (2)播放控制UI界面主要包括:播放、暂停、快放、慢放播放进度等操作界面。其中,除慢放以外的按钮功能都是通过调用播放控制层提供的接口。慢放功能则通过调整YUV图像播放线程的定时刷新周期来实现,具体参数调整为当前周期乘以慢放倍速。
  (3)附加辅助功能及菜单主要包括:截图、旋转、放大、缩小、拉伸等,都是基于YUV图像的二次处理加工。
  需要强调的是,视频的播放控制并不是由展现层实现,而是由下一层的播放控制层实现,展现层永远只专注于获取下一个YUV图像帧进行播放和二次处理,而不关心具体下一个YUV图像帧如何得到。
  另外,定时刷新线程的刷新周期当不能被1000毫秒整除时,需要进行周期的校正,否则随着时间的延迟,会导致时间误差逐渐增大。校正方式为通过1000毫秒对帧率取余得到余数M,对1000毫秒内的前M个周期增加1毫秒,保证误差在每个1000毫秒内都能得到校正。
  综上所述,展现层设计成只处理YUV图像帧,与具体H.264流无关,这保证了其与下层播放控制层之间的低耦合性。
  2.2 播放控制层
  播放控制层是整个播放框架的视频播放控制逻辑实现,主要处理与视频播放控制相关的功能。他主要提供以下功能:
  (1)为展现层提供视频播放参数。视频播放参数是由下一层的视频解码层提供,主要参数包括:视频帧率、分辨率等。主要用于控制YUV图像帧渲染和定时刷新。
  (2)为展现层提供下一个YUV图像帧数据。播放控制层永远缓存着展现层需要的下一个YUV图像帧,该YUV图像帧主要根据当前播放控制状态,计算帧偏移后的索引号,通过向下一层视频解码层获取对应索引编号的YUV图像帧。
  为了更清楚的描述播放控制层的内部实现机制,假设播放控制层主要有以下几个核心参数:
  (1)当前帧索引号Index,记录当前保存的YUV图像帧索引编号,初始值为0;
  (2)当前播放速度Speed,记录当前视频播放的速度状态,支持0/1/2/4/8/16/32多种播放倍速,初始值为1表示正常速度播放,0表示暂停,其他值表示按照正常播放速度的整数倍快进播放。由于慢放的实现已经在展现层通过调整定时刷新周期实现了,因此,播放控制层只实现快进播放控制,其值只可能为0或者正常播放速度的整数倍。
  播放过程中,播放控制层永远保存着索引号为Index的YUV图像帧,一旦当前YUV图像帧被展现层获取之后,播放控制层马上向视频解码层获取索引为Index+Speed的YUV图像帧,并更新Index索引号为Index+Speed。
  当用户通过展现层调整播放控制参数时,播放控制层相应的修改Speed的值,0表示暂停,1表示正常播放,其他值表示快进的倍速,以此实现视频画面的快进效果。
  可见,播放控制层的播放速度控制主要通过索引号Index和播放速度Speed来实现的,即使是暂停的状态下,展现层的刷新线程仍然是在运行的,只是刷新的都是同一幅YUV图像帧。这样设计的目的是为了简化展现层的设计,同时减少展现层与播放控制层之间的耦合性。   2.3 视频解码层
  视频解码层主要实现两个功能:H.264帧缓存以及H.264帧解码。
  H.264帧缓存:将视频流解析层解析出来的H.264流按照NALU语法结构解析成一个个NALU单元缓存到临时文件中,并建立索引表,索引表中的索引号从0开始编号,将每个NALU单元按照索引号递增依次存储到临时文件中,同时将存储偏移地址、NALU单元数据块大小、NALU数据帧类型保存到索引表中。此外,每个帧索引结构中还必须保存离当前帧最近的上一个I帧的索引号,以便视频帧解码时能够快速遍历。
  H.264帧解码:根据播放控制层提供的索引号,编码出索引号对应的YUV图像帧。这里有一点需要特别强调,我们知道H.264的视频图像帧主要分I帧、P帧和B帧,I帧可以单独解码出一个完整的YUV帧,P帧需要依赖前一个I帧以及当前P帧之间的所有帧(P帧和B帧)才能解码出YUV帧。因此,若当前索引号对应的帧是I帧,则直接根据索引对应的偏移地址和NALU数据块大小,从临时文件中读取除对应的数据块,提交给H.264解码库进行解码即可;若当前索引号对应的帧为P,此时就要用到索引结构中保存的离当前帧最近的上一个I帧索引号了。从上一个I帧索引号开始到当前帧索引号,依次读取对应的数据块提交给解码库进行解码,最后一帧返回的就是当前帧的YUV图像帧。
  需要强调的是,在H.264中,只有I帧、P帧、B帧三种图像帧,而I帧解码又需要依赖SPS、PPS参数。因此,在解析缓存H.264流时,应该把SPS、PPS连同I帧当成一个数据块作为I帧写入临时文件,否则会导致I帧及其后的P帧解码失败。正常情况下,每一个I帧之前都会出现SPS和PPS,但不一定都紧邻I帧。这一点在设计过程中要及时缓存最新的SPS和PPS,以便在碰到I帧的时候,一并写入临时文件中。
  另外,H.264帧解码库可以是第三方厂商解码库,也可以是基于开源框架的FFMPEG,开发者可自行选择。但是为了更加灵活的自动适配解码器,建议将解码库模块化,同样提供二次开发接口,方便扩展。
  综上,视频解码层通过将H.264流进行解析,分解成一个个的帧数据块和帧索引结构,为播放控制层提供基于帧的视频解码。
  2.4 视频流解析层
  视频流解析层的功能就是从各种厂商车载终端产品的视频流中解析出视频播放参数和H.264视频流。
  视频流解析层是保障位于该层之上的其他层能够复用的基础,通过它把各种视频流统一转换成由视频参数和H.264流组成的标准格式,彻底屏蔽上层可复用框架与具体视频数据流的耦合性。
  为了便于对接不同厂商终端产品,视频流解析层本身提供了模块化二次开发接口,允许各个厂商按照开发接口,开发属于各自产品的解析模块,把各自的终端接入到框架中。
  从功能上讲,视频流解析层只是进行数据流格式的转换和筛选,并未涉及具体的视频播放相关的功能,因此实现难度上较小。
  3 总结
  综上所述,基于H.264的可复视频播放框架是一套可以支持二次开发的通用H.264播放的框架,它通过展现层、播放控制层、视频解码层封装了基于H.264的视频播放功能,再通过视频流解析层屏蔽实际视频流的差异,实现真正意义上的可复用。通过它,运营商可以根据不同供货商的产品开发各自的解析模块,实现一套框架对接多种产品,即降低了视频播放软件开发的难度,又保证视频功能和效果上的统一,提高用户体验和监控效率。
  参考文献
  [1]赵炯,陈力.利用VC++实现基于DirectShow的视频播放器开发[J].成都大学学报,2011(04).
  [2]胡兴军.视频编码标准H.264的技术革新及应用[J].影像技术,2009(01).
转载注明来源:https://www.xzbu.com/1/view-7559312.htm