ffmpeg与sdl
ffmpeg编译、使用与常见问题

FFMPEG编译、使用与常见问题一. Linux下FFMPEG的安装与测试 (1)二. FFMPEG编译中出现的一些问题与解决方法 (4)三. FFMpeg简介及命令选项参数 (8)四. FFMPEG与x264的编译 (13)一.Linux下FFMPEG的安装与测试a. 先装mp3在linux下的包:lame-3.97.tar.gz;tar -xvzf lame-3.97.tar.gz;cd lame-3.97;./configure --enable-shared --prefix=/usr/;make;make install;b. 支持Ogg Vorbis:as4自带相应的rpm包,你可以安装一下如下rpm包:libvorbis, libvorbis-devel,libogg, libogg-devel 一般情况下as4都会安装c. 支持xvid x264,现在最流行的两种高质量的压缩格式xvid的编译安装wget /downloads/xvidcore-1.1.0.tar.gztar zvxf xvidcore-1.1.0.tar.gzcd xvidcore-1.1.2/build/generic./configure --prefix=/usr --enable-sharedmakemake installx264的获取用git:git clone git:///x264.gitcd x264./configure --prefix=/usr --enable-sharedmakemake install3d. AC3和dts编码的支持as4系统似乎已经支持ac3编码,编译的时候只要加--enable-a52 --enable-gpl参数就行libdts编译参数tar zxvf libdts-0.0.2.tar.gz./configure --prefix=/usrmakemake installe. mpg4 aac格式支持,由于服务器还针对手机用户服务,所以,类似aac,mpg4铃声格式的支持,我们也得做。
只需四行代码即可简单实现SDL嵌入MFC播放视频和图片2014.2.18

纠结半个多月的SDL嵌入MFC的工作终于实现了,蛋疼的是看了那么多代码,找了好多程序,结果实现只需几行代码!!!我们还是低估SDL了,大家都想错路了。
百度看了好多人写的文章,虽然只有几篇介绍SDL嵌入MFC的文章,但是大致都出自一人之手,都是改写winmain,SDL_main等函数的,我第一次看的时候就感觉改了那么多东西,但是关联都不是很大,只知道要获取控件的ID(你想在哪个控件上播放),MFC的原理就是这样,就是获取各种ID。
第一次实现那位仁兄的显示图片到SDI的功能的时候(我是用DLG实现的),我没发觉为什么显示的时候覆盖了整个对话框,因为要实现播放视频,当时还没调通显示视频的部分,而他代码里只有DrawPict这个函数,所以就没注意。
知道今天当我把视频播放,语音播放功能都实现后回头看的时候才发现,原来最重要的就是那么几行。
好了,不瞎扯了,大家可能着急了,到底怎么实现的SDL播放画面嵌入MFC控件中去的。
下面是代码片段:SDL_Event event;static struct SwsContext *img_convert_ctx;char * filePath="c:/test.mp4";/************************************************************************//* 测试SDL窗口显示到mfc对话框中*//************************************************************************/char variable[256];CWnd* pWnd = this->GetDlgItem(IDC_VIEW); //获取图片控件的窗口指针sprintf(variable,"SDL_WINDOWID=0x%1x",pWnd->GetSafeHwnd()); // 格式化字符串SDL_putenv(variable); //这句是最重要的了,将上面的字符串传入即可//剩下的就是设置视频播放大小的问题了,自己可以随便改SDL_Rect rect; //设置好播放的大小后传入SDL_SetVideoModeRECT rc;pWnd->GetWindowRect(&rc);rect.x = 0;rect.y = 0;rect.w = rc.right-rc.left;rect.h = rc.bottom-rc.top;// Register all formats and codecsavcodec_register_all();av_register_all();if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());exit(1);}以下N行代码都是解码的部分,就不写了,主要写和SDL嵌入有关的下面这句大家是相当的熟悉了,用过SDL播放的都应该知道// Make a screen to put our videoscreen = SDL_SetVideoMode(rect.w, rect.h, 0, 0); //此处需要设置成缩放大小if(!screen) {exit(1);}不知道大家看明白没?其实实现这个功能一共就需要四行代码,大家是不是有种蛋碎的感觉?char variable[256];CWnd* pWnd = this->GetDlgItem(IDC_VIEW); //获取图片控件的窗口指针sprintf(variable,"SDL_WINDOWID=0x%1x",pWnd->GetSafeHwnd()); // 格式化字符串SDL_putenv(variable); //这句是最重要的了,将上面的字符串传入即可只要把上面的SDL_WINDOWID传入后,不管你怎么画图,播放视频,都是在那个控件中显示!这个问题绝对不是我第一个想出来的,肯定有人已经知道,但是就这么一个简单的问题,百度上却没有一个人说明!可见中国的大环境啊!为了刚接触ffmpeg的TX少走弯路我会后续写自己对SDL在MFC中运作的一些体会。
如何用FFmpeg编写一个简单播放器详细步骤介绍

如何用FFmpeg编写一个简单播放器详细步骤介绍(转载)FFmpeg, 播放器, 编写FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具。
FFMPEG 几乎为你把所有的繁重工作都做了,比如解码、编码、复用和解复用。
这使得多媒体应用程序变得容易编写。
它是一个简单的,用C编写的,快速的并且能够解码几乎所有你能用到的格式,当然也包括编码多种格式。
唯一的问题是它的文档基本上是没有的。
有一个单独的指导讲了它的基本原理另外还有一个使用doxygen生成的文档。
这就是为什么当我决定研究 FFMPEG来弄清楚音视频应用程序是如何工作的过程中,我决定把这个过程用文档的形式记录并且发布出来作为初学指导的原因。
在FFMPEG工程中有一个示例的程序叫作ffplay。
它是一个用C编写的利用ffmpeg来实现完整视频播放的简单播放器。
这个指导将从原来Martin Bohme写的一个更新版本的指导开始(我借鉴了一些),基于Fabrice Bellard的ffplay,我将从那里开发一个可以使用的视频播放器。
在每一个指导中,我将介绍一个或者两个新的思想并且讲解我们如何来实现它。
每一个指导都会有一个C源文件,你可以下载,编译并沿着这条思路来自己做。
源文件将向你展示一个真正的程序是如何运行,我们如何来调用所有的部件,也将告诉你在这个指导中技术实现的细节并不重要。
当我们结束这个指导的时候,我们将有一个少于1000行代码的可以工作的视频播放器。
在写播放器的过程中,我们将使用SDL来输出音频和视频。
SDL是一个优秀的跨平台的多媒体库,被用在MPEG播放、模拟器和很多视频游戏中。
你将需要下载并安装SDL开发库到你的系统中,以便于编译这个指导中的程序。
这篇指导适用于具有相当编程背景的人。
至少至少应该懂得C并且有队列和互斥量等概念。
你应当了解基本的多媒体中的像波形一类的概念,但是你不必知道的太多,因为我将在这篇指导中介绍很多这样的概念。
利用C实现实时音视频数据传输系统设计与开发

利用C实现实时音视频数据传输系统设计与开发一、引言随着互联网的快速发展,音视频通信已经成为人们日常生活中不可或缺的一部分。
实时音视频数据传输系统在视频会议、在线教育、远程医疗等领域发挥着越来越重要的作用。
本文将介绍如何利用C语言实现一个高效稳定的实时音视频数据传输系统,涵盖系统设计与开发的方方面面。
二、系统架构设计在设计实时音视频数据传输系统时,首先需要考虑系统的整体架构。
一个典型的音视频传输系统包括采集模块、编码模块、传输模块、解码模块和渲染模块。
采集模块负责从摄像头和麦克风中获取音视频数据,编码模块将原始数据进行压缩编码,传输模块通过网络传输编码后的数据,解码模块将接收到的数据进行解码,最后渲染模块将解码后的数据显示在屏幕上。
三、采集模块设计与实现采集模块是实时音视频传输系统中至关重要的一环。
在C语言中,可以利用开源库如OpenCV来实现音视频数据的采集。
通过OpenCV提供的接口,可以轻松地从摄像头和麦克风中获取音视频数据,并进行预处理操作。
四、编码模块设计与实现编码模块负责对采集到的音视频数据进行压缩编码,以减小数据量并保证传输效率。
在C语言中,可以使用FFmpeg等开源编解码库来实现音视频数据的编码工作。
FFmpeg提供了丰富的API接口,可以方便地对音视频数据进行编解码操作。
五、传输模块设计与实现传输模块是实时音视频传输系统中连接采集端和播放端的桥梁。
在C语言中,可以利用Socket编程来实现音视频数据的传输。
通过Socket套接字接口,可以建立客户端和服务器之间稳定可靠的连接,并实现音视频数据的实时传输。
六、解码模块设计与实现解码模块负责将接收到的音视频数据进行解码操作,以便后续渲染显示。
在C语言中,可以使用FFmpeg等开源库来实现音视频数据的解码工作。
通过FFmpeg提供的API接口,可以轻松地对接收到的音视频数据进行解码操作。
七、渲染模块设计与实现渲染模块是实时音视频传输系统中最终将音视频数据显示在屏幕上的环节。
FFmpeg命令行工具学习(二):播放媒体文件的工具ffplay

FFmpeg命令⾏⼯具学习(⼆):播放媒体⽂件的⼯具ffplay ⼀、简述ffplay是以FFmpeg框架为基础,外加渲染⾳视频的库libSDL构建的媒体⽂件播放器。
⼆、命令格式在安装了在命令⾏中输⼊如下格式的命令:ffplay [选项] ['输⼊⽂件']1. 主要选项'-x width' 强制以 "width" 宽度显⽰'-y height' 强制以 "height" ⾼度显⽰'-an' 禁⽌⾳频'-vn' 禁⽌视频'-ss pos' 跳转到指定的位置(秒)'-t duration' 播放 "duration" 秒⾳/视频'-bytes' 按字节跳转'-nodisp' 禁⽌图像显⽰(只输出⾳频)'-f fmt' 强制使⽤ "fmt" 格式'-window_title title' 设置窗⼝标题(默认为输⼊⽂件名)'-loop number' 循环播放 "number" 次(0将⼀直循环)'-showmode mode' 设置显⽰模式可选的 mode :'0, video' 显⽰视频'1, waves' 显⽰⾳频波形'2, rdft' 显⽰⾳频频带默认值为 'video',你可以在播放进⾏时,按 "w" 键在这⼏种模式间切换'-i input_file' 指定输⼊⽂件2. ⼀些⾼级选项'-sync type' 设置主时钟为⾳频、视频、或者外部。
默认为⾳频。
主时钟⽤来进⾏⾳视频同步'-threads count' 设置线程个数'-autoexit' 播放完成后⾃动退出'-exitonkeydown' 任意键按下时退出'-exitonmousedown' 任意⿏标按键按下时退出'-acodec codec_name' 强制指定⾳频解码器为 "codec_name"'-vcodec codec_name' 强制指定视频解码器为 "codec_name"'-scodec codec_name' 强制指定字幕解码器为 "codec_name"3. ⼀些快捷键'q, ESC' 退出'f' 全屏'p, SPC' 暂停'w' 切换显⽰模式(视频/⾳频波形/⾳频频带)'s' 步进到下⼀帧'left/right' 快退/快进 10 秒'down/up' 快退/快进 1 分钟'page down/page up' 跳转到前⼀章/下⼀章(如果没有章节,快退/快进 10 分钟)'mouse click' 跳转到⿏标点击的位置(根据⿏标在显⽰窗⼝点击的位置计算百分⽐)三、ffplay 播放⾳频播放⾳频⽂件的命令:ffplay shy.mp3这时候就会弹出来⼀个窗⼝,⼀边播放MP3⽂件,⼀边将播放⾳频的图画到该窗⼝上。
ffmpeg编译、使用与常见问题

FFMPEG编译、使用与常见问题一. Linux下FFMPEG的安装与测试 (1)二. FFMPEG编译中出现的一些问题与解决方法 (4)三. FFMpeg简介及命令选项参数 (8)四. FFMPEG与x264的编译 (13)一.Linux下FFMPEG的安装与测试a. 先装mp3在linux下的包:lame-3.97.tar.gz;tar -xvzf lame-3.97.tar.gz;cd lame-3.97;./configure --enable-shared --prefix=/usr/;make;make install;b. 支持Ogg Vorbis:as4自带相应的rpm包,你可以安装一下如下rpm包:libvorbis, libvorbis-devel,libogg, libogg-devel 一般情况下as4都会安装c. 支持xvid x264,现在最流行的两种高质量的压缩格式xvid的编译安装wget /downloads/xvidcore-1.1.0.tar.gztar zvxf xvidcore-1.1.0.tar.gzcd xvidcore-1.1.2/build/generic./configure --prefix=/usr --enable-sharedmakemake installx264的获取用git:git clone git:///x264.gitcd x264./configure --prefix=/usr --enable-sharedmakemake install3d. AC3和dts编码的支持as4系统似乎已经支持ac3编码,编译的时候只要加--enable-a52 --enable-gpl参数就行libdts编译参数tar zxvf libdts-0.0.2.tar.gz./configure --prefix=/usrmakemake installe. mpg4 aac格式支持,由于服务器还针对手机用户服务,所以,类似aac,mpg4铃声格式的支持,我们也得做。
FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放

FFmpeg开发笔记(九):ffmpeg解码rtsp流并使⽤SDL同步播放前⾔ ffmpeg播放rtsp⽹络流和摄像头流。
Demo 使⽤ffmpeg播放局域⽹rtsp1080p海康摄像头:延迟0.2s,存在马赛克 使⽤ffmpeg播放⽹络rtsp⽂件流:偶尔卡顿,延迟看不出 使⽤vlc软件播放局域⽹rtsp1080p海康摄像头:演⽰2s,不存在马赛克 使⽤vlc软件播放⽹络rtsp⽂件流:不卡顿,延迟看不出FFmpeg基本播放流程ffmpeg解码流程 ffmpeg新增API的解码执⾏流程。
新api解码基本流程如下:步骤⼀:注册: 使⽤ffmpeg对应的库,都需要进⾏注册,可以注册⼦项也可以注册全部。
步骤⼆:打开⽂件: 打开⽂件,根据⽂件名信息获取对应的ffmpeg全局上下⽂。
步骤三:探测流信息: ⼀定要探测流信息,拿到流编码的编码格式,不探测流信息则其流编码器拿到的编码类型可能为空,后续进⾏数据转换的时候就⽆法知晓原始格式,导致错误。
步骤四:查找对应的解码器 依据流的格式查找解码器,软解码还是硬解码是在此处决定的,但是特别注意是否⽀持硬件,需要⾃⼰查找本地的硬件解码器对应的标识,并查询其是否⽀持。
普遍操作是,枚举⽀持⽂件后缀解码的所有解码器进⾏查找,查找到了就是可以硬解了(此处,不做过多的讨论,对应硬解码后续会有⽂章进⾏进⼀步研究)。
(注意:解码时查找解码器,编码时查找编码器,两者函数不同,不要弄错了,否则后续能打开但是数据是错的)步骤五:打开解码器 开打解码器的时候,播放的是rtsp流,需要设置⼀些参数,在ffmpeg中参数的设置是通过AVDictionary来设置的。
使⽤以上设置的参数,传⼊并打开获取到的解码器。
AVDictionary *pAVDictionary = 0// 设置缓存⼤⼩ 1024000byteav_dict_set(&pAVDictionary, "buffer_size", "1024000", 0);// 设置超时时间 20sav_dict_set(&pAVDictionary, "stimeout", "20000000", 0);// 设置最⼤延时 3sav_dict_set(&pAVDictionary, "max_delay", "30000000", 0);// 设置打开⽅式 tcp/udpav_dict_set(&pAVDictionary, "rtsp_transport", "tcp", 0);ret = avcodec_open2(pAVCodecContext, pAVCodec, &pAVDictionary);if(ret){LOG << "Failed to avcodec_open2(pAVCodecContext, pAVCodec, pAVDictionary)";return;}步骤六:申请缩放数据格式转换结构体 此处特别注意,基本上解码的数据都是yuv系列格式,但是我们显⽰的数据是rgb等相关颜⾊空间的数据,所以此处转换结构体就是进⾏转换前到转换后的描述,给后续转换函数提供转码依据,是很关键并且⾮常常⽤的结构体。
一种多格式视频插件在图书馆的应用

一种多格式视频插件在图书馆的应用【摘要】针对我校图书馆在利用发布视频资源中遇到的实际问题,提出一种多格式视频插件。
该插件利用ActiveX技术开发,使用了FFMPEG和SDL多媒体库函数,实现对各种格式的视频文件解码和播放,并能嵌入到网页浏览器中使用。
将此插件应用于图书馆的视频点播系统中,可简化视频发布系统的工作,解决了工作中的实际问题。
【关键词】视频插件;格式通用;图书馆The Application of A Multi-format Video Plug-in in the Library【Abstract】For my school library practical problems encountered in the use of Video resources,proposed a multi-format video plug-in.The plug-in using ActiveX technology for development,using FFMPEG and SDL multimedia library functions , to achieve a variety of formats for decoding and playback of video files,and can be embedded into web browser to ing this plug-in in the VOD system of library,can simplify the work of video distribution system,and solve the practical problem in work.【Key words】Video plug-in;General format;Library我校图书馆近年来采购和收集了大量的教学、培训、学习等视频资料,为方便读者使用并保护这些资源的版权,准备通过视频点播网站向读者提供这些视频资源,供读者在线观看。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ffmpeg与sdl电影文件有很多基本的组成部分。
首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置。
AVI和Quicktime就是容器的例子。
接着,你有一组流,例如,你经常有的是一个音频流和一个视频流。
(一个流只是一种想像出来的词语,用来表示一连串的通过时间来串连的数据元素)。
在流中的数据元素被称为帧Frame。
每个流是由不同的编码器来编码生成的。
编解码器描述了实际的数据是如何被编码Coded和解码DECoded的,因此它的名字叫做CODEC。
Divx和MP3就是编解码器的例子。
接着从流中被读出来的叫做包Packets。
包是一段数据,它包含了一段可以被解码成方便我们最后在应用程序中操作的原始帧的数据。
根据我们的目的,每个包包含了完整的帧或者对于音频来说是许多格式的完整帧。
基本上来说,处理视频和音频流是很容易的:在这个程序中使用ffmpeg来处理多种媒体是相当容易的,虽然很多程序可能在对帧进行操作的时候非常的复杂。
因此在这篇指导中,我们将打开一个文件,读取里面的视频流,而且我们对帧的操作将是把这个帧写到一个PPM文件中。
打开文件首先,来看一下我们如何打开一个文件。
通过ffmpeg,你必需先初始化这个库。
(注意在某些系统中必需用<ffmpeg/avcodec.h>和<ffmpeg/avformat.h>来替换)这里注册了所有的文件格式和编解码器的库,所以它们将被自动的使用在被打开的合适格式的文件上。
注意你只需要调用av_register_all()一次,因此我们在主函数main()中来调用它。
如果你喜欢,也可以只注册特定的格式和编解码器,但是通常你没有必要这样做。
现在我们可以真正的打开文件:我们通过第一个参数来获得文件名。
这个函数读取文件的头部并且把信息保存到我们给的AVFormatCont ext结构体中。
最后三个参数用来指定特殊的文件格式,缓冲大小和格式参数,但如果把它们设置为空NULL或者0,libavformat将自动检测这些参数。
这个函数只是检测了文件的头部,所以接着我们需要检查在文件中的流的信息:这个函数为pFormatCtx->streams填充上正确的信息。
我们引进一个手工调试的函数来看一下里面有什么:现在pFormatCtx->streams仅仅是一组大小为pFormatCtx->nb_streams的指针,所以让我们先跳过它直到我们找到一个视频流。
流中关于编解码器的信息就是被我们叫做"codec context"(编解码器上下文)的东西。
这里面包含了流中所使用的关于编解码器的所有信息,现在我们有了一个指向他的指针。
但是我们必需要找到真正的编解码器并且打开它:有些人可能会从旧的指导中记得有两个关于这些代码其它部分:添加CODEC_FLAG_TRUNCATED到p CodecCtx->flags和添加一个hack来粗糙的修正帧率。
这两个修正已经不在存在于ffplay.c中。
因此,我必需假设它们不再必要。
我们移除了那些代码后还有一个需要指出的不同点:pCodecCtx->time_base现在已经保存了帧率的信息。
time_base是一个结构体,它里面有一个分子和分母(AVRational)。
我们使用分数的方式来表示帧率是因为很多编解码器使用非整数的帧率(例如NTSC使用29.97fps)。
保存数据现在我们需要找到一个地方来保存帧:因为我们准备输出保存24位RGB色的PPM文件,我们必需把帧的格式从原来的转换为RGB。
FFMPE G将为我们做这些转换。
在大多数项目中(包括我们的这个)我们都想把原始的帧转换成一个特定的格式。
让我们先为转换来申请一帧的内存。
即使我们申请了一帧的内存,当转换的时候,我们仍然需要一个地方来放置原始的数据。
我们使用avpict ure_get_size来获得我们需要的大小,然后手工申请内存空间:av_malloc是ffmpeg的malloc,用来实现一个简单的malloc的包装,这样来保证内存地址是对齐的(4字节对齐或者2字节对齐)。
它并不能保护你不被内存泄漏,重复释放或者其它malloc的问题所困扰。
现在我们使用avpicture_fill来把帧和我们新申请的内存来结合。
关于AVPicture的结成:AVPicture结构体是AVFrame结构体的子集――AVFrame结构体的开始部分与AVPicture结构体是一样的。
最后,我们已经准备好来从流中读取数据了。
读取数据我们将要做的是通过读取包来读取整个视频流,然后把它解码成帧,最好后转换格式并且保存。
这个循环过程是比较简单的:av_read_frame()读取一个包并且把它保存到AVPacket结构体中。
注意我们仅仅申请了一个包的结构体――ffmpeg为我们申请了内部的数据的内存并通过packet.data指针来指向它。
这些数据可以在后面通过av_free_packet()来释放。
函数avcodec_decode_video()把包转换为帧。
然而当解码一个包的时候,我们可能没有得到我们需要的关于帧的信息。
因此,当我们得到下一帧的时候,avco dec_decode_video()为我们设置了帧结束标志frameFinished。
最后,我们使用img_convert()函数来把帧从原始格式(pCodecCtx->pix_fmt)转换成为RGB格式。
要记住,你可以把一个AVFrame结构体的指针转换为AVPicture结构体的指针。
最后,我们把帧和高度宽度信息传递给我们的SaveFrame函数。
现在我们需要做的是让SaveFrame函数能把RGB信息定稿到一个PPM格式的文件中。
我们将生成一个简单的PPM格式文件,请相信,它是可以工作的。
我们做了一些标准的文件打开动作,然后写入RGB数据。
我们一次向文件写入一行数据。
PPM格式文件的是一种包含一长串的RGB数据的文件。
如果你了解HTML色彩表示的方式,那么它就类似于把每个像素的颜色头对头的展开,就像#ff0000#ff0000....就表示了了个红色的屏幕。
(它被保存成二进制方式并且没有分隔符,但是你自己是知道如何分隔的)。
文件的头部表示了图像的宽度和高度以及最大的RGB值的大小。
现在,回顾我们的main()函数。
一旦我们开始读取完视频流,我们必需清理一切:你会注意到我们使用av_free来释放我们使用avcode_alloc_fram和av_malloc来分配的内存。
上面的就是代码!下面,我们将使用Linux或者其它类似的平台,你将运行:如果你使用的是老版本的ffmpeg,你可以去掉-lavutil参数:大多数的图像处理函数可以打开PPM文件。
可以使用一些电影文件来进行测试。
SDL和视频为了在屏幕上显示,我们将使用SDL.SDL是Simple Direct Layer的缩写。
它是一个出色的多媒体库,适用于多平台,并且被用在许多工程中。
你可以从它的官方网站的网址/上来得到这个库的源代码或者如果有可能的话你可以直接下载开发包到你的操作系统中。
按照这个指导,你将需要编译这个库。
(剩下的几个指导中也是一样)SDL库中有许多种方式来在屏幕上绘制图形,而且它有一个特殊的方式来在屏幕上显示图像――这种方式叫做YUV覆盖。
YUV(从技术上来讲并不叫YUV而是叫做YCbCr)是一种类似于RGB方式的存储原始图像的格式。
粗略的讲,Y是亮度分量,U和V是色度分量。
(这种格式比RGB复杂的多,因为很多的颜色信息被丢弃了,而且你可以每2个Y有1个U和1个V)。
SDL的YUV覆盖使用一组原始的YUV 数据并且在屏幕上显示出他们。
它可以允许4种不同的YUV格式,但是其中的YV12是最快的一种。
还有一个叫做YUV420P的YUV格式,它和YV12是一样的,除了U和V分量的位置被调换了以外。
420意味着它以4:2:0的比例进行了二次抽样,基本上就意味着1个颜色分量对应着4个亮度分量。
所以它的色度信息只有原来的1/4。
这是一种节省带宽的好方式,因为人眼感觉不到这种变化。
在名称中的P表示这种格式是平面的――简单的说就是Y,U和V分量分别在不同的数组中。
FFMPEG可以把图像格式转换为YUV420P,但是现在很多视频流的格式已经是YUV420P的了或者可以被很容易的转换成YUV420P格式。
于是,我们现在计划把指导1中的SaveFrame()函数替换掉,让它直接输出我们的帧到屏幕上去。
但一开始我们必需要先看一下如何使用SDL库。
首先我们必需先包含SDL库的头文件并且初始化它。
SDL_Init()函数告诉了SDL库,哪些特性我们将要用到。
当然SDL_GetError()是一个用来手工除错的函数。
创建一个显示现在我们需要在屏幕上的一个地方放上一些东西。
在SDL中显示图像的基本区域叫做面surface。
这就创建了一个给定高度和宽度的屏幕。
下一个选项是屏幕的颜色深度――0表示使用和当前一样的深度。
(这个在OS X系统上不能正常工作,原因请看源代码)现在我们在屏幕上来创建一个YUV覆盖以便于我们输入视频上去:正如前面我们所说的,我们使用YV12来显示图像。
显示图像前面那些都是很简单的。
现在我们需要来显示图像。
让我们看一下是如何来处理完成后的帧的。
我们将原来对RGB处理的方式,并且替换SaveFrame()为显示到屏幕上的代码。
为了显示到屏幕上,我们将先建立一个AVPicture结构体并且设置其数据指针和行尺寸来为我们的YUV覆盖服务:首先,我们锁定这个覆盖,因为我们将要去改写它。
这是一个避免以后发生问题的好习惯。
正如前面所示的,这个AVPicture结构体有一个数据指针指向一个有4个元素的指针数据。
由于我们处理的是YUV420 P,所以我们只需要3个通道即只要三组数据。
其它的格式可能需要第四个指针来表示alpha通道或者其它参数。
行尺寸正如它的名字表示的意义一样。
在YUV覆盖中相同功能的结构体是像素pixel和程度pitc h。
(程度pitch是在SDL里用来表示指定行数据宽度的值)。
所以我们现在做的是让我们的覆盖中的pic t.data中的三个指针有一个指向必要的空间的地址。
类似的,我们可以直接从覆盖中得到行尺寸信息。
像前面一样我们使用img_convert来把格式转换成PIX_FMT_YUV420P。
绘制图像但我们仍然需要告诉SDL如何来实际显示我们给的数据。
我们也会传递一个表明电影位置、宽度、高度和缩放大小的矩形参数给SDL的函数。
这样,SDL为我们做缩放并且它可以通过显卡的帮忙来进行快速缩放。
现在我们的视频显示出来了!让我们再花一点时间来看一下SDL的特性:它的事件驱动系统。