李芳芳,苏凯雄
(福州大学 物理与信息工程学院,福建 福州 350108)
基于FFmpeg的H.264格式转换器的设计与实现
李芳芳,苏凯雄
(福州大学 物理与信息工程学院,福建 福州 350108)
针对视频编码压缩传输需要,给出了一种基于FFmpeg的H.264格式转换器的设计方法,实现了对H.264码流数据的快速解码、压缩、再编码的功能。该转换器具有工作效率较高等特点,适合于实时传输应用。实验结果表明,转换后的码流经过一系列处理之后,在客户端接收到的视频画面稳定无抖动、播放流畅。
FFmpeg;格式转换器;H.264;实时传输;移植;压缩
随着信息技术的迅速发展,网络视频监控技术已经广泛地应用于各个领域。目前视频数据产生的数据量也是越来越大,如何在有限的资源下更好地利用这些数据,成为了大家研究的重点[1]。视频压缩与视频格式转换是解决上述问题的重要手段。H.264是近年来被广泛应用的视频压缩编码标准,具有压缩率高、网络适应性强、抗干扰性能好等优点。传统的远程视频监控系统所需软硬件资源大,系统传输带宽要求高、时延长、实时性不高[2],本文给出了一种适用于实时视频监控系统采集端软件,在Windows系统上基于FFmpeg的H.264格式转换器的解决方法,着重介绍了FFmpeg的移植与实时视频编码模块的实现。
1.1H.264编码标准
H.264是一种新的视频编码标准,它在保留原有视频编码优点的基础上,提出了以往视频编解码无法比拟的一些优点,如低误码率、网络适应能力强、容错能力强等[3]。H.264分为视频编解码层(VCL)和网络抽象层(NAL),VCL包含codec的信令处理功能如转换、量化、运动补偿预测机制以及循环过滤器,NAL封装VCL编码器输出的片段到网络抽象层单元(NAL Units),它适用于通过包网路传输或面向包的多路复用环境中,用于实际的传输[4]。NALU的头结构由一个字节组成,主要包含以下3种信息:
forbidden_zero_bit:1个比特,在H.264中这一位必须为0。
nal_ref_idc:2个比特,取值范围是00~11,用来表示NAL的优先级。取值越大表示该NAL越重要,需要优先受到保护。如果NAL是属于参考帧的片或序列参数集(SPS)、图像参数集(PPS)这些重要的单位时,nal_ref_idc的值必须为0。
nal_unit_type:5个比特,用来表示NALU单元的类型。
1.2FFmpeg简介
FFmpeg是一套基于Linux操作系统的,集音视频录制、格式转换与编解码为一体的开源解决方案,也可在大多数操作系统中编译和使用[5]。它不仅包含了多种音视频编解码库,同时还支持基于流媒体的实时流的传送。FFmpeg包含了几个与视频处理相关的结构体,其中,AVFrame是数据流在视频编解码过程中用来保存数据缓存的结构体,从数据流读出的数据首先保存在AVPacket中。结构体AVPacket中定义有包的大小、流索引(决定该流为视频流还是音频流)、显示时间戳(Presentation Time Stamp,PTS)、解码时间戳(Decoding Time Stamp,DTS)等与音视频相关的属性值[6]。
基于FFmpeg的H.264格式转换器是视频监控系统中PC采集端软件的一个功能模块,需要将FFmpeg编译成DLL(动态链接库)文件供PC采集端编解码和压缩时使用。移植过程是在Windows XP、已安装VS2008软件的计算机上进行的,编译过程中采用的是ffmpeg-1.2.1,x264-snapshot-20141218-2245,mysy-1.0版本。移植流程主要分为以下几个步骤:
1)MinGW编译
将yasm.exe以及c99wrap.exe、c99conv.exe的路径添加到计算机环境变量PATH中;修改MinGW解压路径下的fstab文件。如果不存在fstab文件,则复制一份fstab.sample到当前目录,然后改名为fstab,再修改其内容为相对应的解压路径与安装路径;修改MinGWmsys1.0路径下的msys.bat文件,在文件开头加入VS2008的安装路径。
2)x264编译
由于FFmpge不支持H.264格式编码,因此要用FFmpeg库的函数和数据结构进行H.264格式编解码,需要结合x264库使用[7]。首先下载last_x264.tar.bz2,运行msys.bat,并切换到x264所在目录,运行以下命令:
./configure --enable-shared --enable-static --disable-asm --prefix=/mingw/x264_build
/mingw/x264_build是最后生成文件的保存目录,需要事先创建x264_build文件夹。可在x264目录中的config.log查看运行日志。接着运行make和make install,完成后会在x264_build的lib文件夹中生成库文件。
3)FFmpeg编译
下载ffmpeg-1.2.1.tar.bz2并且解压缩,运行msys.bat,切换到ffmpeg目录下,运行相应的./configure命令。/mingw/ffmpeg_build是生成文件的保存目录,需要事先定义;/mingw/x264_build/include和/mingw/x264_build/lib是编译x264生成的头文件和库文件路径。configure成功后,运行make和make install,完成后在ffmpeg_build文件夹中生成所需文件。
视频格式转换器主要实现的功能是将前端摄像头实时采集的H.264格式的视频流解码成YUV格式的数据,然后对YUV数据进行再压缩编码形成新的视频数据流,最后将码流数据发送给实时视频监控系统的客户端。该过程主要调用上一节封装好的FFmpeg的动态链接库的接口,完成对输入视频的解码、压缩与再编码的功能。如图1所示,前端摄像头输出的H.264视频数据传送给采集端,采集端的格式转换器通过调用On_RecvRalu()回调函数获得H.264数据格式的原始码流,再实例化一个FfmpegVideoDec类的对象,该类的主要功能是对H.264格式码流数据解码成YUV数据格式,然后将解码得到的YUV数据传入VideoEncCallback()函数中,通过实例化FfmpegVideoResize类,调用该方法对YUV数据进行压缩,最后对FfmpegVid-eoEnc类进行实例化并对压缩后的YUV数据再一次编码成H.264格式数据的码流。
图1 格式转换器的设计与实现流程
3.1解码模块
解码模块主要功能是将H.264格式的视频数据解码成YUV格式的数据,相比RGB色彩空间要求3个独立的视频信号同时传输,YUV占用的传输带宽更少,并且易于实现与压缩,方便传输与处理,所以更加适合于在实时视频监控系统中使用。
解码模块的实现如图2所示,首先通过调用Ffmpeg库中的avcodec_register_all()对编解码器进行注册,再向avcodec_find_decoder() 函数中传入相应的参数信息AVCodecID选择H.264解码器。通过avcodec_alloc_context3()函数分配一个AVCodecContext上下文环境,并调用avcodec_open2()对其进行初始化。AVCodecContext是描述编解码器上下文的数据结构,它可以向编解码器提供许多需要的参数信息,是一个十分重要的数据结构类型。通过调用avcodec_alloc_frame()为AVFrame类型的数据结构pFrame分配空间以便用于存储解码后的数据。在进行解码前需要判断数据是否为一帧的开头,H.264的一帧数据是通过观察二进制码流分析出来的,它是由一个AU(Access Unit)构成,一个AU是由多个连续的NALU组成。每一帧图像一般在开头有一个单元分隔符,两个单元分隔符之间的数据包就是一帧图像。如果NALU对应为一帧的开始,则用4个字节表示,即0x00000001。在H.264规定有一种类型为09的NALU,即编码器在完成一个AU编码后,会在码流中插入一个类型为09的NALU。如果使用了该标识符,帧将由0x0000000109作为结尾。所以解码器只需要从码流中搜索类型为09的NALU即可判断一个AU。判断数据为一帧的开始后再调用av_init_packet()对AVPacket类型的数据进行初始化。然后通过调用avcodec_decode_video2()函数解码一帧数据,输入AVPacket类型的数据,输出后的数据存入AVFrame类型的结构体,函数的返回值即解码所使用的码流字节数。最后再判断got_pic的值是否为1,其中got_pic是avcodec_decode_video2()的第三个参数int*got_picture_ptr数据类型的变量,该变量指示是否有解码数据输出。当got_pic为1时拷贝保存解码出来的数据完成解码功能。
图2 解码模块实现流程
3.2压缩及编码模块
在压缩编码过程中,主要是将YUV数据进行压缩,再将压缩后的数据编码成H.264格式的视频数据。压缩及编码模块的实现流程如图3所示,首先调用sws_getContext()函数返回上下文句柄,并设置原始图像的宽和高以及输出图像的宽和高,然后通过执行函数sws_scale()函数对原始YUV视频数据进行压缩,初始图像的分辨率为1 280×720,设定输出的图像分辨率为352×288。使用avcodec_find_encoder()函数选择设定的ID相应的编码器。在初始化上下文环境并对其设置默认值以后,初始化一个数据类型AVFrame的变量并设置参数,然后调用av_init_packet()函数对AVPakcet类型的变量进行初始化,用于编码存储数据使用。然后通过调用ret=avcodec_encode_video2()编码一帧视频数据,最后判断ret的值,如果大于或者等于0即将指针指向下一帧数据等待编码。
图3 压缩及编码模块实现流程
测试环境是在一台内存为2 Gbyte并在装有XP系统的PC上,前端摄像头型号为海康威视DS-2CD3210D-13,运行环境是VS2008。经测试,解码器解码一次最长时间约16 ms,编码器编码速率为10 f/s(帧/秒),码率为120 kbit/s,原始分辨率是1 280×720,压缩后分辨率为352×288,即cif编码分辨率。原始摄像头采集的视频图像与经过格式转换器处理后接收的图像如图4和图5所示,原始图像较为清晰,传输后的图像相比图4较为模糊,具体可见两图中的“Camera 01”字样和小电视边缘等细节部分。实现的格式转换器在视频监控系统中正常使用,效果良好。
图4 前端摄像头采集的原始视频图像
图5 经压缩编码传输后的视频图像
本文论述了基于FFmpeg开源视频解决方案在Windows平台上的H.264格式转换器的设计与实现。为了提高编解码效率,将FFmpeg移植到Windows平台上,便于格式转换器的开发与使用。文中主要实现了将前端摄像头采集的H.264格式视频数据进行解码、压缩并再编码,最后传送到客户端。本文实现的H.264格式转换器可以很好地适用于实时传输系统当中,并且经转换器处理后的画面较为清晰,编解码速率快,在Windows平台上移植的FFmpeg动态链接库使用方便,大大提高开发效率。
[1]李蔷.H.264视频编码码率控制技术研究[D].上海:上海交通大学,2005.
[2]肖远东,蔡声镇.基于iOS平台的移动视频监控软件设计[J].计算机工程,2015,41(2):268-271.
[3]SRINIVASAN K S.The effects of priority levels and buffering on the statistical multiplexing of singe-layer H.264/AVC and SVC en-coded video stream[J].IEEE transactions on broadcasting,2011,56(3):281-286.
[4]陈阳.基于ffmpeg内核的H.264实时视频解码器开发[J].四川兵工学报,2014,35(9):103-104.
[5]胡聪,周甜,唐璐丹.基于FFMPEG的跨平台视频编解码研究[J].武汉理工大学学报,2011,33(11):139-142.
[6]梁发云,陈志文,王婧,等.基于FFmpeg的立体视频播放技术研究[J].电视技术,2013,37(11):27-29.
[7]韦崇岭,裴海龙.基于无人机H264视频传输系统的设计与实现[J].计算机测量与控制,2012,20(1):209-211.
责任编辑:闫雯雯
Design and implementation of H.264 format converter based on FFmpeg
LI Fangfang,SU Kaixiong
(CollegeofPhysicsandInformationEngineering,FuzhouUniversity,Fuzhou350108,China)
For the need of video coding compression and transmission,the method of H.264 format converter based on FFmpeg to achieve the fast decoding,compression,re-encoding functions to the H.264 data stream is given.The converter has high efficiency and other charecteristics which is suitable for the real time transmission applications.The result shows that the converted data stream after a series of processes,the video images which is client received are stable and playback smoothly.
FFmpeg; format converter;H.264; real-time transmission;transplant;compression
TN919.8
ADOI:10.16280/j.videoe.2016.07.008
福建省产学重大项目(2015H6014)
2015-10-21
文献引用格式:李芳芳,苏凯雄. 基于FFmpeg的H.264格式转换器的设计与实现[J].电视技术,2016,40(7):32-35.
LI F F,SU K X. Design and implementation of H.264 format converter based on FFmpeg [J].Video engineering,2016,40(7):32-35.