2024年1月18日发(作者:)

本科毕业论文(设计)

题 目 基于C++的视频播放器

院 系 计算机科学与技术

专 业 计算机科学与技术(网络工程方向)

姓 名

学 号

学习年限 2009年9月至2013年7月

指导教师

申请学位 理学学士学位

2013年 3 月 24 日

基于C++的视频播放器

摘 要

随着计算机的广泛运用,Internet的迅速发展,多媒体技术也是迅速发展。各种音频视频资源在网上随处可见,在人们的日常生活中,播放器几乎不可缺少,于是各种播放器紧跟着发展起来。如今,软件市场上的视频播放器层出不群,如:暴风影音、PPS、风行等。

本文设计实现了一个简单的视频播放器的过程,了解播放器的功能实现,掌握播放器开发的相关技术,同时利用软件工程的相关理论知识,了解软件开发的方法与步骤。该软件利用FFmpeg解码库及简易直控媒体层开发而成。整个系统从操作简便、实用、功能全面的要求出发,体现了该视频播放器的稳定性,拓展性,兼容性的特点。本设计其中一个最大的特色就是该播放器基本支持所有格式的音视频,能实现一些比较少有格式的播放。

该播放器可以支持的播放:

1. 多媒体容器所有格式;

2. 视频编码所有格式;

3. 音频编码所有格式;

关键词:Linux;C++;FFmpeg;全格式

The video player based on C++

ABSTRACT

With the extensive application of computer, the rapid development of

Internet, the multimedia technology is also developing rapidly. A variety of

audio and video resources can be seen everywhere on the Internet, in people's

daily life, almost indispensable player, then all kinds of player development.

Now, the video player software on the market that do not group, such as:

Storm video, PPS, popular.

This paper presents the design and implementation process of a simple

video player, understand the player to achieve the function, master the related

technical player development, at the same time, the software engineering

theory knowledge, understanding of software development methodology and

steps. The software uses FFmpeg decoder library and simple direct control

layer and media development. The whole system from the point of view of

simple, practical, functional requirements of comprehensive, reflects the

stability, the video player development, compatibility. This design is one of

the biggest feature is the player basic support all formats of audio and video,

can achieve some less of a format.

The player can support broadcast:

1. All multimedia container format

2. All multimedia container format

3. All audio coding format

KEYWORDS: Linux;C++;FFmpeg;

Full format

目 录

引言 ........................................................................................................................................................... 1

1 简介 ....................................................................................................................................................... 2

1.1 播放器举例简介......................................................................................................................... 2

1.1.1 暴风影音.......................................................................................................................... 2

1.1.2 风行影音.......................................................................................................................... 3

1.2 几种常见编码格式简介 ............................................................................................................. 4

2 软件开发平台和开发工具介绍 ............................................................................................................ 5

2.1软件开发平台.............................................................................................................................. 5

2.2 C++语言 ...................................................................................................................................... 6

2.3 ffmpeg .......................................................................................................................................... 6

2.3.1 ffmpeg简介 ...................................................................................................................... 6

2.3.2 ffmpeg媒体文件处理 ...................................................................................................... 7

2.3.3 ffmpeg文件解析库和编解码库 ...................................................................................... 7

3 系统总体设计 ....................................................................................................................................... 7

3.1 系统的数据流图设计 ................................................................................................................. 7

3.2 系统的第二层数据流图的设计 ................................................................................................. 8

3.2.1 数据提取层 ...................................................................................................................... 8

3.2.2 数据预处理层 .................................................................................................................. 8

3.2.3 解码层.............................................................................................................................. 8

3.3 系统的第三层数据流图的设计 ................................................................................................. 9

4 系统详细设计和实现............................................................................................................................ 9

4.1 ffmpeg库的初始化 ..................................................................................................................... 9

4.2 视频文件的打开....................................................................................................................... 10

4.3 视频文件格式的解析模块 ....................................................................................................... 10

4.3.1 文件格式解析 ................................................................................................................ 10

4.3.2 文件格式解析器的主要工作 ........................................................................................ 11

4.3.3 文件格式解析器的实现 ................................................................................................ 11

4.4 视频解码模块........................................................................................................................... 14

4.4.1 视频编码格式简介 ........................................................................................................ 14

4.4.2 视频编码定义 ................................................................................................................ 14

4.4.3 视频编码原理 ................................................................................................................ 15

4.5 音频解码模块........................................................................................................................... 16

4.5.1 什么是采样率和采样大小 ............................................................................................ 17

4.5.2 什么是有损和无损 ........................................................................................................ 17

4.5.3 为什么要使用音频压缩技术 ........................................................................................ 17

4.5.4 频率与采样率的关系 .................................................................................................... 18

4.5.5 流特征............................................................................................................................ 18

5 系统的运行与测试 ............................................................................................................................. 19

5.1 软件测试 .................................................................................................................................. 19

5.2 测试评价 .................................................................................................................................. 20

参考文献 ................................................................................................................................................. 21

引言

C++语言是一种优秀的面向对象程序设计语言,,它在C语言的基础上发展而来,但它比C语言更容易为人们学习和掌握。C++以其独特的语言机制在计算机科学的各个领域中得到了广泛的应用。面向对象的设计思想是在原来结构化程序设计方法基础上的一个质的飞跃,C++完美地体现了面向对象的各种特性。

随着多媒体的不断发展,多媒体格式极不统一,那么支持各种不同格式的多媒体播放器则成为一种需求。

大学的课程里面开设了软件工程这一门课程,通过学习,我对程序设计等理论知识有了较深刻的认识,同时也掌握了一定的软件开发理论,借助这次毕业设计,把这些理论知识付诸实践。设计的这个视频播放器简单方便、易操作,能够播放常见的音频视频格式,满足一般用户听歌看电影的需求。但是我自己能力有限,缺少开发经验,此次设计肯定存在许多不足之处,随着我知识的积累和经验的增加,我将会逐步对它完善。

1

1 简介

1.1 播放器举例简介

本小节举例介绍下列比较常见的播放器,比如国产暴风影音、风行影音等。比较分析它们的功能,及特有的解码功能等;另外再介绍下几种常见的编码格式以及它们的特点。

1.1.1 暴风影音

暴风影音是暴风网际公司推出的一款视频播放器,该播放器兼容大多数的视频和音频格式。从2003年开始,5年来,暴风的工程师分析了数以十万计的视频文件,掌握了超过500种视频格式的支持方案。到2009年1月,暴风影音每天使用用户超过2200万,暴风影音成功的帮助了超过1亿5000万的中国互联网用户轻松的观看视频。来自艾瑞的数据显示:截止2009年1月,暴风影音每天为互联网用户播放超过1.5亿个/次视频文件;每天,有2200万人点击蓝色的胶片图标,打开暴风影音这款软件;每天,通过暴风影音播放的视频文件占中国所有互联网视频播放量的50%。暴风影音已经成为中国最大的互联网视频播放平台。2008年7月,全新的暴风影音2008第一次涵盖了互联网用户观看视频的所有服务形式,包括:本地播放、在线直播、在线点播、高清播放等;

软件特色:通过自动侦测用户的电脑硬件配置;自动匹配相应的解码器、渲染链;自动调整对硬件的支持。它提供和升级了系统对常见绝大多数影音文件和流的支持,包括 :RealMedia、QuickTime、MPEG2、MPEG4 (ASP/AVC)、VP3/6/7、Indeo、FLV 等流行视频格式;AC3/DTS/LPCM/AAC/OGG/MPC/APE/FLAC/TTA/WV 等流行音频格式;3GP/Matroska/MP4/OGM/PMP/XVD 等媒体封装及字幕支持等。暴风影音采用 NSIS 封装,为标准的 Windows 安装程序,特点是单文件多语种(目前为简体中文 + 英文),具有稳定灵活的安装、卸载、维护和修复功能,并对集成的解码器组合进行了尽可能的优化和兼容性调整,适合普通的大多数以多媒体欣赏或简单制作为主要使用需求的用户。

2

在兼容问题上,暴风影音和一些软件部相容,但问题不大,可以解决,但是要用户自己解决。比如安装暴风影音后,丽台电视卡无法使用,解决也很简单,下载安装该电视卡全套的最新版本驱动和电视播放软件即可(注意仅仅驱动是不行的,一定要包括播放软件);播放AVI的时候画面出错或CPU占有率奇高——解决方案:通常是解码器兼容问题;等等,虽然有点麻烦,但可以解决。

从以上简单的介绍可以看出,暴风影音整体还是个很强大,很好用的播放器。单个人看来,它仍然有一些问题。暴风影音截止到现在版本已经升级很多次了,几乎每次升级都添加了新功能,优化了某些功能,修正个别bug,到现在暴风能播放几百种格式的媒体文件,功能庞大。这些看似很好,但是对于一般用户来说看电影听音乐看网上视频能使用几种格式的文件,甚至有部分用户不能上网,对于这些用户来说绝大部分的功能是白费了,浪费资源而已。

1.1.2 风行影音

功能特色:独创双播放内核,更快速、更清晰、更流畅,国内首家独创真正双播放内核影音播放器,聚合MPlayer和MPC强大优势功能,实现快速解码,挑战最快播放极限,播放影片更快速、更清晰、更流畅;全面支持高清影片播放(无需安装第三方软件),从2.1版本起,全面支持高清影片播放,且无需另外安装第三方软件,全面支持HD-DVD/BD-DVD、VC-1、EAC3、EVO、TS、TP、MKV 等高清格式影片;独创高清智能连接技术、VC-1智能桥接技术、启用显卡硬解功能,充分发挥显卡硬解MPEG2,让高清播放更流畅;播放206种影音格式;多分层过滤解码,全面提升影片兼容播放,在双播放内核的基础上采用多分层过滤解码,保证不同格式不同编码的影片都能找到对应的分离器和解码器并顺畅播放,大大提升了影片播放的兼容性;智能连续剧播放,智能连续剧识别,无需多次选择播放连续剧影片,自动连续剧播放,让您不间断欣赏影片更顺畅、更舒心;跳过连续剧片头/片尾,在播放连续剧影片时,可以通过按 F9/F10 来设置跳过连续剧的片头/片尾,让剧情播放无缝连接;还可以变看边下载,很方便用户等等。

从上述功能(并不完全,只是介绍一下特色功能)可以看出,风行影音也是个很不错的播放器,特别是其在双播放内核、高清影音上别具特色。但是对于部分在网上看视频的用户来说有一点缺陷,它不支持在线播放。

3

1.2 几种常见编码格式简介

MP3格式: MP3具有不错的压缩比,使用LAME编码的中高码率的mp3,听感上已经非常接近源WAV文件。使用合适的参数,LAME编码的MP3很适合于音乐欣赏。由于MP3推出年代已久,加之不错的音质及压缩比,不少游戏也使用mp3作事件音效和背景音乐。几乎所有著名的音频编辑软件也提供了对MP3的支持,可以将mp3像wav一样使用,但由于mp3编码是有损的,因此多次编辑后,音质会急剧下降,mp3并不适合保存素材,但作为作品的demo确实相当优秀的。mp3长远的历史和不错的音质,使之成为应用最广的有损编码之一,网络上可以找到大量的mp3资源,mp3player日渐成为一种时尚。不少VCD Player、DVD Player甚至手机都可以播放mp3,mp3是被支持的最好的编码之一。MP3也并非完美,在较低码率下表现不好。MP3也具有流媒体的基本特征,可以做到在线播放。 其音质好,压缩比比较高,被大量软件和硬件支持,应用广泛。适用于比较高要求的音乐欣赏。

WMV格式:一种独立于编码方式的在Internet上实时传播多媒体的技术标准,Microsoft公司希望用其取代QuickTime之类的技术标准以及WAV、AVI之类的文件扩展名。WMV的主要优点在于:可扩充的媒体类型、本地或网络回放、可伸缩的媒体类型、流的优先级化、多语言支持、扩展性等。

WMA格式:WMA的全称是Windows Media Audio,是微软力推的一种音频格式。WMA格式是以减少数据流量但保持音质的方法来达到更高的压缩率目的,其压缩率一般可以达到1:18,生成的文件大小只有相应MP3文件的一半。这对只装配32M的机型来说是相当重要的,支持了WMA和RA格式,意味着32M的空间在无形中扩大了2倍。此外,WMA还可以通过DRM(Digital Rights Management)方案加入防止拷贝,或者加入限制播放时间和播放次数,甚至是播放机器的限制,可有力地防止盗版。

RMVB格式:这是一种由RM视频格式升级延伸出的新视频格式,它的先进之处在于RMVB视频格式打破了原先RM格式那种平均压缩采样的方式,在保证平均压缩比的基础上合理利用比特率资源,就是说静止和动作场面少的画面场景采用较低的编码速率,这样可以留出更多的带宽空间,而这些带宽会在出现快速运动的画面场景时被利用。这样在保证了静止画面质量的前提下,大幅地提高了运动图像的画面质量,从而图像质量和文件大小之间就达到了微妙的平衡。

RM格式:Networks公司所制定的音频视频压缩规范称之为Real Media,用户可 4

以使用RealPlayer或RealOne Player对符合RealMedia技术规范的网络音频/视频资源进行实况转播,并且RealMedia还可以根据不同的网络传输速率制定出不同的压缩比率,从而实现在低速率的网络上进行影像数据实时传送和播放。这种格式的另一个特点是用户使用RealPlayer或RealOne Player播放器可以在不下载音频/视频内容的条件下实现在线播放。

MPEG格式:它的英文全称为Moving Picture Expert Group,即运动图像专家组格式,家里常看的VCD、SVCD、DVD就是这种格式。MPEG文件格式是运动图像压缩算法的国际标准,它采用了有损压缩方法减少运动图像中的冗余信息,说的更加明白一点就是MPEG的压缩方法依据是相邻两幅画面绝大多数是相同的,把后续图像中和前面图像有冗余的部分去除,从而达到压缩的目的(其最大压缩比可达到200:1)。目前MPEG格式有三个压缩标准,分别是MPEG-1、MPEG-2、和MPEG-4。

AVI格式:音频视频交错(Audio Video Interleaved)的英文缩写。AVI这个由微软公司发表的视频格式在视频领域已经存在好几个年头了。AVI格式调用方便、图像质量好,但缺点就是文件体积过于庞大,压缩标准不统一。

2 软件开发平台和开发工具介绍

2.1软件开发平台

Linux流行是因为它具有许多诱人之处。

(1)源代码几乎全部是开放的。

Linux是一款免费的操作系统,用户可以通过网络或其他途径免费获得,并可以任意修改其源代码。这是其他的操作系统所做不到的。正是由于这一点,来自全世界的无数程序员参与了Linux的修改、编写工作,程序员可以根据自己的兴趣和灵感对其进行改变。这让Linux吸收了无数程序员的精华,不断壮大。

(2)可以运行在许多硬件平台上。

Linux可以运行在多种硬件平台上,如具有x86、680x0、SPARC、Alpha等处理器的平台。此外Linux还是一种嵌入式操作系统,可以运行在掌上电脑、机顶盒或游戏机上。2001年1月份发布的Linux 2.4版内核已经能够完全支持Intel 64位芯片架构。同时Linux也支持多处理器技术。多个处理器同时工作,使系统性能大大提高。

(3)多用户、多任务

5

Linux支持多用户,各个用户对于自己的文件设备有自己特殊的权利,保证了各用户之间互不影响。多任务则是现在电脑最主要的一个特点,Linux可以使多个程序同时并独立地运行。

2.2 C++语言

C++语言是一种优秀的面向对象程序设计语言,它在C语言的基础上发展而来,但它比C语言更容易为人们学习和掌握。C++以其独特的语言机制在计算机科学的各个领域中得到了广泛的应用。面向对象的设计思想是在原来结构化程序设计方法基础上的一个质的飞跃,C++完美地体现了面向对象的各种特性。

对于要解决实际问题的程序员而言,C++使程序设计变得更有乐趣。C++是一门通用目的的程序设计语言,它是一个更好的C、支持数据抽象、支持面向对象程序设计及支持范型程序设计。在程序设计这方面,C++支持良好的设计方案、提供用于程序组织的语言设施、能将独立开发的部件组合成完整的软件。

2.3 ffmpeg

2.3.1 ffmpeg简介

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它包括了目前领先的音/视频编码库libavcodec。 FFmpeg是在Linux下开发出来的,但它可以在包括Windows在内的大多数操作系统中编译。这个项目是由Fabrice Bellard发起的,现在由Michael Niedermayer主持。可以轻易地实现多种视频格式之间的相互转换,例如可以将摄录下的视频avi等转成现在视频网站所采用的flv格式。

ffmpeg包括一组软件,ffmpeg用于对媒体文件进行处理,ffserver是一个http的流媒体服务器,ffplay是一个基于SDL的 简单播放器。两个库文件libavcodec和libavformat。

ffmpeg项目由以下几部分组成:

 ffmpeg 视频文件转换命令行工具,也支持经过实时电视卡抓取和编码成视频文件。

 ffserver 基于HTTP(RTSP正在开发中)用于实时广播的多媒体服务器,也支持时间平移

 ffplay 用 SDL和FFmpeg库开发的一个简单的媒体播放器

 libavcodec 一个包含了所有FFmpeg音视频编解码器的库.为了保证最优性能和 6

高可复用性,大多数编解码器从头开发的.

 libavformat 一个包含了所有的普通音视格式的解析器和产生器的库。

2.3.2 ffmpeg媒体文件处理

ffmpeg是基于linux开发的,但同时也支持在linux,windows,wince,android等操作系统下的编译及库函数调用,从而播放器视频文件的底层处理。

在linux系统下,ffmpeg支持直接的命令行操作,实现没有包装的直接播放,解析,解码或者转换,剪切,合并,分离视频和音频。

基本用法如下:

ffmpeg -i INPUTfile [OPTIONS] OUTPUTfile

由于Linux把设备视为文件,因此-i选项后可以跟设备名。比如DV,视频卡,光驱或者其它的各类设备。

如果没有输入文件,那么视音频捕捉就会起作用。

作为通用的规则,选项一般用于下一个特定的文件。如果你给 –b 64选项,改选会设置下一个视频速率。对于原始输入文件,格式选项可能是需要的。

缺省情况下,ffmpeg试图尽可能的无损转换,采用与输入同样的音频视频参数来输出。

2.3.3 ffmpeg文件解析库和编解码库

ffmpeg作为目前领先的视频解析、解码和编码的开源程序,其在视频解析、解码和编码方面有着很大的影响。最重要的是ffmpeg编译成动态库或者静态库的时候都提供了有着强大功能和简易使用的接口,同时ffmpeg程序支持在linux和windows等很多操作系统下的编译。这两个特性就使得目前很多支持大多主流格式的播放器都是调用ffmpeg库进行解析和解码,如Linux下的mplayer和windows下的暴风影音和Gomplayer等主流播放器。

这里也将调用ffmpeg这个强大的视频解析和解码库实现最底层的视频格式解析和解码,从而能够实现目前主流视频格式的正常播放。

3 系统总体设计

3.1 系统的数据流图设计

系统的顶层数据通过用户输入文件名,然后经过系统分析,显示该多媒体 内容,如图3-1所示。

7

图3-1 顶层数据流图

3.2 系统的第二层数据流图的设计

图3-2 第二层数据流图

3.2.1 数据提取层

该层完成主要功能为从本地文件获取媒体数据,将媒体数据存入缓冲区,按照缓冲策略将数据包发送给数据预处理层,该层有两个线程,两个线程分别为接受音频和视频RTP数据的线程。

3.2.2 数据预处理层

本层对本地文件的预处理完全依赖与FFmpeg提供的功能文件解封装功能,而媒体文件的预处理需将一个或多个RTP数据包整合在一起。

3.2.3 解码层

解码层主要应用FFmpeg库作为播放器的解码模块,如图3-2该部分代码支持包括avi、3gp、MPEG-4等90多种解码格式及文件格式,并且经过修剪优化后的FFmpeg代码效率和效能都得到了很大的提高。

8

3.3 系统的第三层数据流图的设计

系统的第三层数据流图主要实现两个模块,FFmpeg多媒体文件解析库和FFmpeg音视频解码库。如图3-3所示,播放器打开视频文件,将视频文件的数据流输入parser,parser解析视频文件的文件头,再根据数据块的id判定该数据块时视频还是音频数据。根据音视频数据的判定,将解析后的纯数据输入到相应的视频或者音频解码器。如果是视频数据,输入的视频压缩数据经过视频解码器解码后形成原始的视频数据,此时调用SDL库将视频画面在屏幕上显示出来;如果是音频数据,输入的音频压缩数据,经过音频解码器解码后形成原始的未压缩的音频数据,此时调用底层的音频驱动就可以将音频数据产生的声音通过speaker播放出来。这里的parser,video decoder和audio decoder将调用ffmpeg库进行解析和解码。

图3-3 第三层数据流图

4 系统详细设计和实现

4.1 ffmpeg库的初始化

整个视频文件格式的解析以及视频解码和音频解码部分都会调用ffmpeg库的的接口函数。在调用接口函数之前需要先初始化所有将要使用到的解析器,和各视频解码器以及音频解码器,注册所有的文件格式和编解码器的库。

9

#include //包含ffmpeg所有文件格式的解析函数

#include //包含ffmpeg所有视频及音频编码格式的解码函数

av_register_all(); //注册所有的文件格式解析器和视频音频解码器

ffmpeg库中提供了每一种文件格式和编解码器的初始化接口,但是由于这个播放器需要实现全格式视频的解析和解码,所以需要初始化所有的文件格式解析器和解码器。为此,使用ffmpeg提供的一个av_register_all()函数来初始化所有的文件格式解析器和解码器。

4.2 视频文件的打开

第一步是通过命令行参数的形式,向播放器中传入文件名,并读入文件头得部分信息。

AVFormatContext *pFormatCtx; //存放视频文件的所有信息

// Open video file

if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)

//打开命令行参数argv[1]所指示的文件名,将所得到的信息放在 pFormatCtx的数据结构中

return -1; // Couldn't open file //如果打开文件失败,返回-1。操作结束

4.3 视频文件格式的解析模块

4.3.1 文件格式解析

需要解析文件的格式就必须要知道文件格式的数据布局。文件格式解析的过程就是根据已知的数据布局,在相应的文件位置找到相关的数据。

下图是简单的视频文件的示意图。

图4-1 视频文件示例图

从上图可以看出,每个视频文件都会有一个存放视频相关信息的文件头(file

header),文件头会面紧跟着连续的数据块。这些数据块以时间戳(每个数据块播放的时间)的顺序摆放,每个数据块的数据只可能是视频数据或者音频数据,没有音频和 10

视频数据同时在一个数据块的情况。

4.3.2 文件格式解析器的主要工作

文件格式的解析器(demuxer)是整个视频文件播放过程中最重要的部分。

其主要的功能有:

1.解析文件头(file header),取得文件头中关于视频的很多信息,如:视频编码格式,音频编码格式,分辨率,最大码率,平均码率,文件时长等对后面的解码过程必不可少的信息。

2.从文件数据流中依次取得一个数据块,解析每个数据块的头,并把每个数据块的纯数据送到相应的解码器中进行解码。

3.同步A/V,demuxer根据数据块中的时间戳和整个播放过程的时间戳来控制整个播放过程的进度。当数据块中的时间戳提前时,demuxer会等待时间符合的时候才送出下一个数据块;如果数据块中的时间滞后,demuxer就会丢弃当前的数据块,取得下一个数据块。

4.实现视频文件播放的拖动(seek)功能。播放器收到拖动的命令后,demuxer会从数据流中取得播放器传下来的拖动点的数据块进行解析,并把解析后的纯数据给解码器进行解码。

4.3.3 文件格式解析器的实现

由于av_open_input_file()函数只是检测了文件的头部,所以接着我们需要检查在文件中的流的信息:

if(av_find_stream_info(pFormatCtx)<0) //检查在文件中的流的信息

return -1; // Couldn't find stream information //如果检查失败,则返回-1

av_find_stream_info(pFormatCtx)函数取得文件相关的信息,填充在pFormatCtx->streams数据结构里。

下面根据pFormatCtx->streams数据结构上的codec_type参数取得视频和音频编码格式的编号。

int i;

AVCodecContext *pCodecCtx;

// Find the first video stream

videoStream=-1;

for(i=0; inb_streams; i++)

if(pFormatCtx->streams->codec->codec_type==CODEC_TYPE_VIDEO) {

videoStream=i; //循环验证每个流的id,如果有符合视频流的编号,则将此流的编号赋值给videoStream变量,此值将在后面取得每个数据块时判别流ID的凭证。

break;

}

if(videoStream==-1)

11

return -1; // Didn't find a video stream //如果videoStream没有被重新赋值,则表示该文件没有视频流(纯音频文件,如mp3,wav等格式中只有音频,没有视频,videoStream==-1

// Get a pointer to the codec context for the video stream

pCodecCtx=pFormatCtx->streams[videoStream]->codec;

同样,音频流也是如此找到的:

int i;

AVCodecContext *pCodecCtx;

// Find the first audio stream

audioStream=-1;

for(i=0; inb_streams; i++)

if(pFormatCtx->streams->codec->codec_type==CODEC_TYPE_AUDIO) {

audioStream=i; //循环验证每个流的id,如果有符合音频流的编号,则将此流的编号赋值给audioStream变量,此值将在后面取得每个数据块时判别流ID的凭证。

break;

if(audioStream==-1)

return -1; // Didn't find a audio stream //如果audioStream没有被重新赋值,则表示该文件没有音频流(纯视频文件,如m4v,m1v等格式中只有音频,没有音频,audioStream==-1

// Get a pointer to the codec context for the audio stream

pCodecCtx=pFormatCtx->streams[audioStream]->codec;

流中关于编解码器的信息称为"codec context"(编解码器上下文)。这里面包含了流中所使用的关于编解码器的所有信息。

下面根据已经找到的编码格式来寻找相应的解码器。只要连接上符合的解码器,将后来取得的数据块解析后输入解码器进行解码,就实现了视频播放的主要功能。

AVCodec *pCodec;

// Find the decoder for the video or audio stream

pCodec=avcodec_find_decoder(pCodecCtx->codec_id); // 根据已经找到的pCodecCtx->codec_id的值用轮询的方式找到符合的解码器ID。

if(pCodec==NULL) {

fprintf(stderr, "Unsupported codec!n");

return -1; // Codec not found //如果找不到符合条件的解码器,则表示播放器不能播放该视频,返回-1值。

12

}

// Open codec

if(avcodec_open(pCodecCtx, pCodec)<0) //找到合适的解码器,打开解码器

return -1; //Could not open codec

上面的操作已经取得视频文件的头信息,并取得文件中的视频和音频流,同时已经找到了相应的视频解码器和音频解码器。

申请一块内存来保存帧:

AVFrame *pFrame;

// Allocate video frame

pFrame=avcodec_alloc_frame();

因为需要输出保存24位RGB色的PPM文件,所以必须把帧的格式从原来的转换为RGB。

先为转换来申请一帧的内存。

Allocate an AVFrame structure

pFrameRGB=avcodec_alloc_frame();

if(pFrameRGB==NULL)

return -1;

当转换的时候,需要一个地方来放置原始的数据。使用avpicture_get_size来获得所需要的大小, 然后手工申请内存空间:

uint8_t *buffer;

int numBytes;

// Determine required buffer size and allocate buffer

numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,

pCodecCtx->height);

buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

现在使用avpicture_fill来把帧和新申请的内存来结合。

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,

pCodecCtx->width, pCodecCtx->height)

前面是视频播放器的准备工作,下面将进行视频文件的播放。视频的播放是一个通过循环读取包来读取整个视频流,然后把它解码成帧,最后通过SDL播放。

不断循环的过程,从视频文件中取得一个数据块就会引起一个循环周期。

int frameFinished;

AVPacket packet;

i=0;

while(av_read_frame(pFormatCtx, &packet)>=0) {

if(_index==videoStream) {

13

avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,

, );

if(frameFinished) {

img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,

(AVPicture*)pFrame, pCodecCtx->pix_fmt,

pCodecCtx->width, pCodecCtx->height);

}

}

av_free_packet(&packet);

}

av_read_frame()读取一个包并且把它保存到AVPacket结构体中。这些数据可以在后面通过av_free_packet()来释 放。函数avcodec_decode_video()把包转换为帧。然而当解码一个包的时候,可能没有得到我们需要的关于帧的信息。因此,当得 到下一帧的时候,avcodec_decode_video()设置了帧结束标志frameFinished。最后,使用

img_convert()函数来把帧从原始格式(pCodecCtx->pix_fmt)转换成为RGB格式。再调用SDL库进行显示。

4.4 视频解码模块

4.4.1 视频编码格式简介

所谓视频编码方式就是指通过特定的压缩技术,将某个视频格式的文件转换成另一种视频格式文件的方式。目前视频流传输中最为重要的编解码标准有国际电联的H.261、H.263,运动静止图像专家组的M-JPEG和国际标准化组织运动图像专家组的MPEG系列标准,此外在互联网上被广泛应用的还有Real-Networks的RealVideo、微软公司的WMV以及Apple公司的QuickTime等。

4.4.2 视频编码定义

MPEG是活动图像专家组(Moving Picture Experts Group)的缩写,于1988年成立,是为数字视/音频制定压缩标准的专家组,目前已拥有300多名成员,包括IBM、SUN、BBC、NEC、INTEL、AT&T等世界知名公司。MPEG组织最初得到的授权是制定用于“活动图像”编码的各种标准,随后扩充为“及其伴随的音频”及其组合编码。后来针对不同的应用需求,解除了“用于数字存储媒体”的限制,成为现在制定“活动图像和音频编码”标准的组织。MPEG组织制定的各个标准都有不同的目标和应用,目前已提出MPEG-1、MPEG-2、MPEG-4、MPEG-7和MPEG-21标准。

视频压缩技术是计算机处理视频的前提。视频信号数字化后数据带宽很高,通常在20MB/秒以上,因此计算机很难对之进行保存和处理。采用压缩技术以后通常数据带宽右以降到1-10MB/秒,这样就可以将视频信号保存在计算机中并作相应的处理。 14

常用的算法是由ISO制订的,即JPEG和MPEG算法。JPEG是静态图像压缩标准,适用于连续色调彩色或灰度图像,它包括两部分:一是基于DPCM(空间线性预测)技术的无失真编码,一是基于DCT(离散余弦变换)和哈夫曼编码的有失真算法,前者压缩比很小,主要应用的是后一种算法。在非线性编辑中最常用的是MJPEG算法,即Motion JPEG。它是将视频信号50帧/秒(PAL制式)变为25帧/秒,然后按照25帧/秒的速度使用JPEG算法对每一帧压缩。通常压缩倍数在3.5-5倍时可以达到Betacam的图像质量。MPEG算法是适用于动态视频的压缩算法,它除了对单幅图像进行编码外还利用图像序列中的相关原则,将冗余去掉,这样可以大大提高视频的压缩比。前MPEG-I用于VCD节目中,MPEG-II用于VOD、DVD节目中。

音频视频编码及文件格式(容器)是一个很庞大的知识领域,完整的说清楚,那就需要些写成一本教材了。这里先就几个简单的概念问题作以介绍:

首先要分清楚媒体文件和编码的区别: 文件是既包括视频又包括音频、甚至还带有脚本的一个集合,也可以叫容器;

文件当中的视频和音频的压缩算法才是具体的编码。 也就是说一个.avi文件,当中的视频可能是编码a,也可能是编码b,音频可能是编码5,也可能是编码6,具体的用那种编码的解码器,则由播放器按照avi文件格式读取信息去调用了。

4.4.3 视频编码原理

视频图像数据有极强的相关性,也就是说有大量的冗余信息。其中冗余信息可分为空域冗余信息和时域冗余信息。压缩技术就是将数据中的冗余信息去掉(去除数据之间的相关性),压缩技术包含帧内图像数据压缩技术、帧间图像数据压缩技术和熵编码压缩技术。

去时域冗余信息

使用帧间编码技术可去除时域冗余信息,它包括以下三部分:

- 运动补偿

运动补偿是通过先前的局部图像来预测、补偿当前的局部图像,它是减少帧序列冗余信息的有效方法。

- 运动表示

不同区域的图像需要使用不同的运动矢量来描述运动信息。运动矢量通过熵编码进行压缩。

- 运动估计

运动估计是从视频序列中抽取运动信息的一整套技术。

注:通用的压缩标准都使用基于块的运动估计和运动补偿。

去空域冗余信息

主要使用帧内编码技术和熵编码技术:

- 变换编码

帧内图像和预测差分信号都有很高的空域冗余信息。变换编码将空域信号变 15

换到另一正交矢量空间,使其相关性下降,数据冗余度减小。

- 量化编码

经过变换编码后,产生一批变换系数,对这些系数进行量化,使编码器的输出达到一定的位率。这一过程导致精度的降低。

- 熵编码

熵编码是无损编码。它对变换、量化后得到的系数和运动信息,进行进一步的压缩。

int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,

int *got_picture_ptr,

AVPacket *avpkt)

{

int ret;

*got_picture_ptr= 0;

if((avctx->coded_width||avctx->coded_height) &&

avcodec_check_dimensions(avctx,avctx->coded_width,avctx->coded_height))

return -1;

if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size){

ret = avctx->codec->decode(avctx, picture, got_picture_ptr,

avpkt);

emms_c(); //needed to avoid an emms_c() call before every return;

if (*got_picture_ptr)

avctx->frame_number++;

}else

ret= 0;

return ret;

}

4.5 音频解码模块

自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。

16

4.5.1 什么是采样率和采样大小

声音其实是一种能量波,因此也有频率和振幅的特征,频率对应于时间轴线,振幅对应于电平轴线。波是无限光滑的,弦线可以看成由无数点组成,由于存储空间是相对有限的,数字编码过程中,必须对弦线的点进行采样。采样的过程就是抽取某点的频率值,很显然,在一秒中内抽取的点越多,获取得频率信息更丰富,为了复原波形,一次振动中,必须有2个点的采样,人耳能够感觉到的最高频率为20kHz,因此要满足人耳的听觉要求,则需要至少每秒进行40k次采样,用40kHz表达,这个40kHz就是采样率。我们常见的CD,采样率为44.1kHz。光有频率信息是不够的,我们还必须获得该频率的能量值并量化,用于表示信号强度。量化电平数为2的整数次幂,我们常见的CD位16bit的采样大小,即2的16次方。采样大小相对采样率更难理解,因为要显得抽象点,举个简单例子:假设对一个波进行8次采样,采样点分别对应的能量值分别为A1-A8,但我们只使用2bit的采样大小,结果我们只能保留A1-A8中4个点的值而舍弃另外4个。如果我们进行3bit的采样大小,则刚好记录下8个点的所有信息。采样率和采样大小的值越大,记录的波形更接近原始信号。

4.5.2 什么是有损和无损

根据采样率和采样大小可以得知,相对自然界的信号,音频编码最多只能做到无限接近,至少目前的技术只能这样了,相对自然界的信号,任何数字音频编码方案都是有损的,因为无法完全还原。在计算机应用中,能够达到最高保真水平的就是PCM编码,被广泛用于素材保存及音乐欣赏,CD、DVD以及我们常见的WAV文件中均有应用。因此,PCM约定俗成了无损编码,因为PCM代表了数字音频中最佳的保真水准,并不意味着PCM就能够确保信号绝对保真,PCM也只能做到最大程度的无限接近。我们而习惯性的把MP3列入有损音频编码范畴,是相对PCM编码的。强调编码的相对性的有损和无损,是为了告诉大家,要做到真正的无损是困难的,就像用数字去表达圆周率,不管精度多高,也只是无限接近,而不是真正等于圆周率的值。

4.5.3 为什么要使用音频压缩技术

要算一个PCM音频流的码率是一件很轻松的事情,采样率值×采样大小值×声道数 bps。一个采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的WAV文件,它的数据速率则为 44.1K×16×2 =1411.2 Kbps。我们常说128K的MP3,对应的WAV的参数,就是这个1411.2 Kbps,这个参数也被称为数据带宽,它和ADSL中的带宽是一个概念。将码率除以8,就可以得到这个WAV的数据速率,即176.4KB/s。这表示存储一秒钟采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的音频信号,需要176.4KB的空间,1分钟则约为10.34M,这对大部分用户是不可接受的,尤其是喜欢在电脑上听音乐的朋友,要降低磁盘占用,只有2种方法,降低采样指标或者压缩。降低指标是不可取的,因此专家们研发了各种压缩方案。由于用途和针对的目标市场不一样,各种音频压缩编码所达到的音质和压缩比都不一样,在后面的文章中我们都会一一提到。有一点是可以肯定的,他们都压缩过。

17

4.5.4 频率与采样率的关系

采样率表示了每秒对原始信号采样的次数,我们常见到的音频文件采样率多为44.1KHz,这意味着什么呢?假设我们有2段正弦波信号,分别为20Hz和20KHz,长度均为一秒钟,以对应我们能听到的最低频和最高频,分别对这两段信号进行40KHz的采样,我们可以得到一个什么样的结果呢?结果是:20Hz的信号每次振动被采样了40K/20=2000次,而20K的信号每次振动只有2次采样。显然,在相同的采样率下,记录低频的信息远比高频的详细。这也是为什么有些音响发烧友指责CD有数码声不够真实的原因,CD的44.1KHz采样也无法保证高频信号被较好记录。要较好的记录高频信号,看来需要更高的采样率,于是有些朋友在捕捉CD音轨的时候使用48KHz的采样率,这是不可取的!这其实对音质没有任何好处,对抓轨软件来说,保持和CD提供的44.1KHz一样的采样率才是最佳音质的保证之一,而不是去提高它。较高的采样率只有相对模拟信号的时候才有用,如果被采样的信号是数字的,请不要去尝试提高采样率。

4.5.5 流特征

随着网络的发展,人们对在线收听音乐提出了要求,因此也要求音频文件能够一边读一边播放,而不需要把这个文件全部读出后然后回放,这样就可以做到不用下载就可以实现收听了。也可以做到一边编码一边播放,正是这种特征,可以实现在线的直播,架设自己的数字广播电台成为了现实。

int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples,

int *frame_size_ptr,

AVPacket *avpkt)

{

int ret;

if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size){

//FIXME remove the check below _after_ ensuring that all audio check that

the available space is enough

if(*frame_size_ptr < AVCODEC_MAX_AUDIO_FRAME_SIZE){

av_log(avctx,

return -1;

}

if(*frame_size_ptr < FF_MIN_BUFFER_SIZE ||

*frame_size_ptr < avctx->channels * avctx->frame_size * sizeof(int16_t)){

av_log(avctx,

*frame_size_ptr);

18

AV_LOG_ERROR, "buffer smaller than

AVCODEC_MAX_AUDIO_FRAME_SIZEn");

AV_LOG_ERROR, "buffer %d too smalln",

return -1;

}

ret = avctx->codec->decode(avctx, samples, frame_size_ptr, avpkt);

avctx->frame_number++;

}else{

ret= 0;

*frame_size_ptr=0;

}

return ret;

}

5 系统的运行与测试

为了保证软件的质量和可靠性,力求在分析、设计等各个开发阶段,对软件进行严格的技术评审。测试的目的是以最少的时间和人力找出软件中潜在的各种错误和缺陷。系统可根据需要开发各阶段的规格说明和程序内部结构而精心设计的一批测试用例,并利用这些测试用例去运行程序,以发现程序错误的过程。

5.1 软件测试

测试是在软件投入生产性运行之前必做的工作。为了保证软件的质量和可靠性,力求在分析、设计等各个开发阶段,对软件进行严格的技术评审。为了发现尽可能地发现错误,进行软件测试。测试的目的是以最少的时间和人力找出软件中潜在的各种错误和缺陷。

测试软件的方法一般有两种:

(1)黑盒测试:已经知道了程序具有的功能,通过测试来检验是否每个功能都能正常使用。

有效性测试是在模拟的环境(可能就是开发的环境,运行黑盒测试的方法,验证所测试软件是否满足需求规格说明书的需求。为此,需求首先制定测试计划,规定要做测试的种类。还需要制定一组测试步骤,描述具体的测试用例。通过实施预定的测试计划和测试步骤,确定软件的特性是否与需求相符,确保所有的软件功能需求都能达 19

到,所有的文档都正确且便于使用。

(2)白盒测试 :知道程序内部工作过程,通过测试来检验内部动作是否按照规格说明书的规定正进行。使用白盒测试方法,主要想对程序模块进行如下的检查:

 对程序模块的所有独立的执行路径至少测试一次;

 对所有的逻辑判断,去“真”与取“假”的两种情况都能至少测试一次;

 在循环的边界和运行界限内执行循环体;

测试内部数据结构的有效等等。

5.2 测试评价

经过测试,该应用程序能够较好的实现多媒体的播放;能够多多媒体进行播放和暂停;能够对多媒体进行快进和倒退,并实现显示文件的时间长度,播放的时间位置;能够对声音的大小进行调节;能够拥有一定的安全性、兼容性和实用性。但在安全性上存在一定的漏洞;功能相对完善,基本支持所有格式的多媒体;界面相对简单,所以总体评价为中等。

希望能得到高老师的指导得以更加完善此系统,添补漏洞。

结束语

从确定课程设计的题目到现在将近三个月的时间,我们的”播放器”已初步形成。通过本次设计,又学习了一门新的软件和许多视频解码的知识。

对于这一门软件来说我们算是初学者,所以我们先要从基础开始学习ffmpeg解码库,通过查找相关资料和老师这个学期的课堂讲解内容来了解到熟悉这个软件。所以从专业角度来讲,我们的整个设计还不太规范和完善。但是 20

通来这次设计,我们在软件开发这个方面累积了许多知识和经验,为以后从事计算机工作打下了基础。同时,在学习和设计中:

1.体验到linux系统的强大性、多功能性、全面性和多样性。

2.通过设计播放器,知道了如何开始一个系统的制作和其制作的工作流程与步骤。

3.学会了如何使用C语言来开发设计一个系统。

4.了解了如何应用SDL进行多媒体开发

参考文献

[1]C++ Primer中文版,Stanley n,Josee Lajoie,Barbara 著,李师贤,蒋爱军等译。

[2] 陈明编著,linux基础与应用,清华大学出版社,2005年1月。

[3] 李兆形,原浩译,软件安全开发生命周期,电子工业出版社,2008年1月。

致谢

在程序的设计与开发过程中,我得到了很多老师和同学的热情帮助,收获也很多。感谢三年年来传授我知识的老师们,更要感谢我的家人对我学业上的支持和鼓励,感谢所有关心帮助过我的人 21