基于libavcodec+libavformat的视频播放器
- 格式:doc
- 大小:171.00 KB
- 文档页数:26
一、概述为了解决在线无广告播放youku网上的视频。
(youku把每个视频切换成若干个小视频)。
视频资源解析可以从网上获取,此网站根据你输入的优酷的播放网页地址解析成若干个真实的视频地址。
二、实现首先搜索关闭网络播放器(流媒体播放器的实现方法)得出的结论,目前主流的播放器分三大阵营微软,苹果,基于FFmpeg内核的。
所以我决定从ffmpeg开源的播放器入手。
最出名的ffmpeg播放器vcl播放器,开源免费。
最后选择放弃。
原因1 依赖于vcl的68M的plugins和libvlccore.dll,libvlc.dll项目生成文件过大。
2即使这样不能解决播放多段视频卡顿现象。
最后决定使用ffmpeg官方的ffpaly播放器只有1000多行(很激动),使用ffmpeg编解码,使用sdl做显示。
本想只修改下就行了。
结果发现里面代码结构过于复杂,搞懂每行很是吃力。
而且是用sdl做显示,sdl需要句柄。
而我这个是为wpf项目量身定做的。
Wpf只有顶层窗口有句柄。
如果是使用wpf嵌入winform控件。
导致此winform控件只能最上层显示(原因是wpf是directui思想实现的)。
所以也放弃了。
决定使用ffmpeg库,自己开发查看网上关于ffmpeg开发的总结。
对ffmpeg开发有个总体方向。
首先我们先把视频搞出来,参考网上 100行代码搞定视频。
然后100行搞定音频网上这样视频音频都已经搞出来了。
但是我们怎么把视频音频一起搞出来呢?Csdn有一份文档网上此文档介绍了用ffmpeg开发视频播放器的详细方法,有注解。
但是已经过时了。
最新的代码在网上但是文档中的思想还是挺受用的。
代码不同,思想是通的。
结论,视频包含视频流,音频流,字幕流(一般没有),音视频同步跟进播放时间戳pts来做的。
视频和音频得出pts的方式有所不同。
具体看文档。
如果按文档的注释,然后根据github的代码,编译我们发现视频可以显示,音频出现乌拉乌拉的杂音。
TCPMP(The Core Pocket Media Player),这是一个应用于智能设备上的开源媒体播放软件。
TCPMP是一个功能强大开放式的开源多媒体播放器,播放器主要由核心框架模块(common工程)和解码器分离器插件组成。
TCPMP的插件非常多,联合几个最常用的插件(ffmpeg、splitter)来说明,其中interface 插件实现TCPMP的界面,由于他和媒体播放没有什么关系,这部分可以完全被替换掉,替换成自己的界面。
ffmpeg工程是系统主要的音视频解码模块,ffmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案。
FFmpeg的开发是基于Linux操作系统,但是可以在大多数操作系统中编译和使用。
ffmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多种编码,A VI、MPEG、OGG、Matroska、ASF等90多种解码。
很多开源播放器都用到了ffmpeg。
但是ffmpeg程序解码效率不是很高,系统仅仅使用了FFmpeg的部分解码功能。
ffmpeg主目录下主要有libavcodec、libavformat和libavutil等子目录。
其中libavcodec 用于存放各个encode/decode模块,libavformat用于存放muxer/demuxer模块,libavutil用于存放内存操作等常用模块。
本系统的媒体文件分离器有单独的splitter模块完成所以不需要libavformat子目录。
ffmpeg目录下libavcodec、libavutil保留子目录。
libmad工程用于MP3文件解码,该工程包含两个功能模块,一个负责解析MP3文件格式,包括MPEG1音频文件 (MP1,MP2,MP3,MPA),读取每一帧音频数据;另一个负责解码MPEG1音频数据,解码代码在libmad子目录中。
libmad是一个开源的高精度 MPEG1音频解码库,支持 MPEG-1(Layer I, Layer II 和 LayerIII,也就是 MP3)。
视频播放器一款融电影搜索、播放等功能为一体的影视播放器。
⏹针对每个项目完成一份需求报告+设计报告;⏹需求包括功能型需求和非功能性需求;⏹设计包括概要设计和详细设计⏹基于嵌入式Linux、WinCE等平台。
linux下播放器设计和开发本文根据DawnLightPlayer的开发经验写成。
DawnLithtPlayer是今天3月份开始,和maddrone一起在业余时间开发的一个跨平台,多线程的播放器,主要是在Linux下面开发的,文中所用示例代码均截自其中。
DawnLightPlayer目前可以运行在Linux和Windows系统上,并使用VC和Python开发了GUI,支持大部分的音视频文件格式和网络流,另外新增对CMMB协议的支持,不支持RMVB, SWF 等尚未公开协议的视频文件格式。
目录:一. 播放器的流程1. 输入2. 解码3. 输出二. 播放器的实现1. 输入实现2. 解码线程实现3. 输出线程实现三. 视频输出库1. SDL (多平台,支持硬件缩放)2. DirectX DirectDraw (win32平台,支持硬件缩放)3. OpenGL (多平台,支持硬件缩放)4. X11 (Linux/Unix)5. FrameBuffer (Linux, 无硬件缩放)四. 音频输出1. OSS (Open Sound System for Linux)2. ALSA (Advanced Linux Sound Architecture)3. DirectSound (WIN32)五. 音视频同步1. 以音频为基准同步视频2. 以视频为基准同步音频3. 同步于一个外部时钟六. 截图1. 使用jpeglib保存成jpeg文件2. 使用libpng保存成png文件七. YUV RGB 软件转换八. 软件缩放一. 播放器的流程1. 输入: 从文件或网络等读取原数据,如x.avi, x.mov, rtsp://xxx, 对原数据进行解析,比如文件,首先要分析文件格式,从文件中取得音视频编码参数,视频时间长度等信息,然后要从其中取出音频编码数据和视频编码数据送到解码部分,这里暂称这种编码源数据块为packet。
`libavcodec` 是 FFmpeg 库中的一个重要组件,用于实现多种音视频编码和解码功能。
在 FFmpeg 中,常用的音视频编码格式包括 H.264、H.265、MPEG-4、AAC 等。
下面是使用 `libavcodec` 实现音视频编码的基本步骤:1. 初始化 AVCodec 和 AVCodecContext在使用 `libavcodec` 进行编码前,需要先初始化 AVCodec 和 AVCodecContext。
AVCodec 表示要使用的编码器,AVCodecContext 则表示编码器的上下文信息,包括编码参数、输出格式等。
可以通过调用 `avcodec_find_encoder()` 函数查找指定编码器,然后通过 `avcodec_alloc_context3()` 函数分配一个 AVCodecContext 对象。
```cppAVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);```2. 配置编码参数在 AVCodecContext 中设置编码参数。
例如,对于 H.264 编码,可以设置帧率、码率、GOP 大小等参数。
```cppcodec_ctx->bit_rate = 1000000;codec_ctx->width = 1280;codec_ctx->height = 720;codec_ctx->time_base = {1, 25};codec_ctx->framerate = {25, 1};codec_ctx->gop_size = 25;codec_ctx->max_b_frames = 0;codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;```3. 打开编码器调用 `avcodec_open2()` 函数打开编码器,使其准备好接收数据进行编码。
ffmpeg开发指南(使用 libavformat 和 libavcodec)Ffmpeg 中的Libavformat和 libavcodec库是访问大多数视频文件格式的一个很好的方法。
不幸的是,在开发您自己的程序时,这套库基本上没有提供什么实际的文档可以用来作为参考(至少我没有找到任何文档),并且它的例程也并没有太多的帮助。
这种情况意味着,当我在最近某个项目中需要用到 libavformat/libavcodec 库时,需要作很多试验来搞清楚怎样使用它们。
这里是我所学习的--希望我做的这些能够帮助一些人,以免他们重蹈我的覆辙,作同样的试验,遇到同样的错误。
你还可以从这里下载一个demo程序。
我将要公开的这部分代码需要0.4.8 版本的ffmpeg库中的 libavformat/libavcodec 的支持(我正在写最新版本)。
如果您发现以后的版本与我写的程序不能兼容,请告知我。
在这个文档里,我仅仅涉及到如何从文件中读入视频流;音频流使用几乎同样的方法可以工作的很好,不过,我并没有实际使用过它们,所以,我没于办法提供任何示例代码。
或许您会觉得奇怪,为什么需要两个库文件 libavformat 和 libavcodec :许多视频文件格式(AVI就是一个最好的例子)实际上并没有明确指出应该使用哪种编码来解析音频和视频数据;它们只是定义了音频流和视频流(或者,有可能是多个音频视频流)如何被绑定在一个文件里面。
这就是为什么有时候,当你打开了一个AVI文件时,你只能听到声音,却不能看到图象--因为你的系统没有安装合适的视频解码器。
所以, libavformat 用来处理解析视频文件并将包含在其中的流分离出来,而libavcodec 则处理原始音频和视频流的解码。
1打开视频文件:首先第一件事情--让我们来看看怎样打开一个视频文件并从中得到流。
我们要做的第一件事情就是初始化libavformat/libavcodec:av_register_all();这一步注册库中含有的所有可用的文件格式和编码器,这样当打开一个文件时,它们才能够自动选择相应的文件格式和编码器。
Unity利⽤FFmpeg实现录屏、直播推流、⾳频视频格式转换、剪裁等功能⽬录⼀、FFmpeg简介。
⼆、FFmpeg常⽤参数及命令。
三、FFmpeg在Unity 3D中的使⽤。
1、FFmpeg 录屏。
2、FFmpeg 推流。
3、FFmpeg 其他功能简述。
⼀、FFmpeg简介对于FFmpeg,其上是这样介绍的:FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created.FFmpeg能够实现对视频⾳频编码、解码、转码、流传输等等⼀系列功能。
它包含有libavcodec, libavutil, libavformat, libavfilter, libavdevice, libswscale,libswresample 库。
其中:libavcodec 是⼀个包含⽤于⾳频/视频编解码器的解码器和编码器的库。
libavutil 是⼀个包含简化编程功能的库,包括随机数⽣成器,数据结构,数学例程,核⼼多媒体实⽤程序等等。
libavformat 是⼀个包含多媒体容器格式的解复⽤器和复⽤器的库。
libavdevice 是⼀个包含输⼊和输出设备的库,⽤于从许多常见的多媒体输⼊/输出软件框架中获取和呈现,包括Video4Linux,Video4Linux2,VfW和ALSA。
libavfilter 是⼀个包含媒体过滤器的库。
libswscale 是⼀个执⾏⾼度优化的图像缩放和⾊彩空间/像素格式转换操作的库。
libswresample 是⼀个执⾏⾼度优化的⾳频重采样,重新矩阵化和样本格式转换操作的库。
⼆、FFmpeg常⽤参数及命令1、命令的格式:ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...2、常⽤参数:-f fmt (input/output) 强制设定输⼊或输出⽂件格式。
ffmpeg 技术原理
FFmpeg是一种音视频处理核心技术,广泛应用于录制、转换和流式传输音频和视频。
以下是FFmpeg技术原理的一些简要介绍:
1.读取视频文件:FFmpeg首先将视频文件读取到内存中,然后进行后续的
处理。
2.解码和编码:在读取视频文件后,FFmpeg对其进行解码,即将原始数据
根据编码定义解析成YUV色彩空间。
接着,FFmpeg会对YUV色彩空间的图形进行压缩处理,生成指定格式的文件。
在这个过程中,FFmpeg可以调整各种参数,如帧率、像素、画质等。
3.依赖库:FFmpeg的实现主要依赖于libavcodec和libavformat等库,它
们提供了编解码和格式转换等功能。
4.跨平台解决方案: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开发指南(使用 libavformat 和 libavcodec)Ffmpeg 中的Libavformat和 libavcodec库是访问大多数视频文件格式的一个很好的方法。
不幸的是,在开发您自己的程序时,这套库基本上没有提供什么实际的文档可以用来作为参考(至少我没有找到任何文档),并且它的例程也并没有太多的帮助。
这种情况意味着,当我在最近某个项目中需要用到 libavformat/libavcodec 库时,需要作很多试验来搞清楚怎样使用它们。
这里是我所学习的--希望我做的这些能够帮助一些人,以免他们重蹈我的覆辙,作同样的试验,遇到同样的错误。
你还可以从这里下载一个demo程序。
我将要公开的这部分代码需要0.4.8 版本的ffmpeg库中的 libavformat/libavcodec 的支持(我正在写最新版本)。
如果您发现以后的版本与我写的程序不能兼容,请告知我。
在这个文档里,我仅仅涉及到如何从文件中读入视频流;音频流使用几乎同样的方法可以工作的很好,不过,我并没有实际使用过它们,所以,我没于办法提供任何示例代码。
或许您会觉得奇怪,为什么需要两个库文件 libavformat 和 libavcodec :许多视频文件格式(AVI就是一个最好的例子)实际上并没有明确指出应该使用哪种编码来解析音频和视频数据;它们只是定义了音频流和视频流(或者,有可能是多个音频视频流)如何被绑定在一个文件里面。
这就是为什么有时候,当你打开了一个AVI文件时,你只能听到声音,却不能看到图象--因为你的系统没有安装合适的视频解码器。
所以, libavformat 用来处理解析视频文件并将包含在其中的流分离出来,而libavcodec 则处理原始音频和视频流的解码。
1打开视频文件:首先第一件事情--让我们来看看怎样打开一个视频文件并从中得到流。
我们要做的第一件事情就是初始化libavformat/libavcodec:av_register_all();这一步注册库中含有的所有可用的文件格式和编码器,这样当打开一个文件时,它们才能够自动选择相应的文件格式和编码器。
视频高清低损压缩命令行实现方案推荐通常我们的MAC录制视频后文件都非常大,15min的视频可以达到2G大小,哪怕是三五分钟视频也有好几遍M所以需要转换,压缩,但是不能降低太多的分辨率。
这里我的御用视频编辑师推荐了一款非常轻量级的命令行工具FFmpeg可以做到,下面是FFmpeg的简短介绍:FFmpeg 是一个自由软件,可以运行音频和视频多种格式的录影、转换、流功能,包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库,以及libavformat——一个音频与视频格式转换库。
“FFmpeg”这个单词中的“FF”指的是“FastForward”。
还专门有人分享了学习它的笔记:https:///feixiao/ffmpeg 我这里因为只用到了一个格式转换及视频压缩的功能,就只抛砖引玉提一下。
安装在mac下面安装ffmpeg 只需要两行代码即可:/usr/bin/ruby -e "$(curl -fsSL https:///Homebrew/install/mast er/install)"brew install ffmpeg其实就是借用了brew来安装ffmpeg。
使用示例代码是:ffmpeg -i old.mov -vcodec libx264 -preset fast -crf 20 -y -vf "scale=1920:-1" -acodec libmp3lame -ab 128k new.mp4参数解释如下:'-i filename (input)’输入文件名'-y (global)’覆盖输出文件而不询问'-vf filtergraph (output)’创建 filtergraph 指定的过滤图,并使用它来过滤流。
'-vcodec codec (output)’设置视频 codec。
'-acodec codec (input/output)’设置音频codec。
100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)简介FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手。
我刚接触FFMPEG的时候也感觉不知从何学起。
因此我把自己做项目过程中实现的一个非常简单的视频播放器(大约100行代码)源代码传上来,以作备忘,同时方便新手学习FFMPEG。
该播放器虽然简单,但是几乎包含了使用FFMPEG 播放一个视频所有必备的API,并且使用SDL显示解码出来的视频。
并且支持流媒体等多种视频输入,处于简单考虑,没有音频部分,同时视频播放采用直接延时40ms的方式。
平台使用VC2010,使用了新版的FFMPEG类库。
流程图没想到这篇文章中介绍的播放器挺受FFMPEG初学者的欢迎,因此再次更新两张流程图,方便大家学习。
此外在源代码上添加了注释,方便理解。
该播放器解码的流程用图的方式可以表示称如下形式:SDL显示YUV图像的流程图:简单解释几句:SDL_Surface就是使用SDL的时候弹出的那个窗口。
在SDL1.x版本中,只可以创建一个SDL_Surface。
SDL_Overlay用于显示YUV数据。
一个SDL_Overlay对应一帧YUV 数据。
SDL_Rect用于确定SDL_Overlay显示的位置。
注意:一个SDL_Overlay可以指定多个不同的SDL_Rect,这样就可以在SDL_Surface不同位置显示相同的内容。
它们的关系如下图所示:下图举了个例子,指定了4个SDL_Rect,可以实现4分屏的显示。
simplest_ffmpeg_player(标准版)代码/*** 最简单的基于FFmpeg的视频播放器* Simplest FFmpeg Player* 本程序实现了视频文件的解码和显示(支持HEVC,H.264,MPEG2等)。
* 是最简单的FFmpeg视频解码方面的教程。
* 通过学习本例子可以了解FFmpeg的解码流程。
* This software is a simplest video player based on FFmpeg.* Suitable for beginner of FFmpeg.*/#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windowsextern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswscale/swscale.h"#include "SDL/SDL.h"};#else//Linux...#ifdef __cplusplusextern "C"{#endif#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libswscale/swscale.h>#include <SDL/SDL.h>#ifdef __cplusplus};#endif#endif//Full Screen#define SHOW_FULLSCREEN 0//Output YUV420P#define OUTPUT_YUV420P 0int main(int argc, char* argv[]){//FFmpegAVFormatContext *pFormatCtx;int i, videoindex;AVCodecContext *pCodecCtx;AVCodec *pCodec;AVFrame *pFrame,*pFrameYUV;AVPacket *packet;struct SwsContext *img_convert_ctx;//SDLint screen_w,screen_h;SDL_Surface *screen;SDL_VideoInfo *vi;SDL_Overlay *bmp;SDL_Rect rect;FILE *fp_yuv;int ret, got_picture;char filepath[]="bigbuckbunny_480x272.h265";av_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){ printf("Couldn't open input stream.\n");return -1;}if(avformat_find_stream_info(pFormatCtx,NULL)<0){printf("Couldn't find stream information.\n");return -1;}videoindex=-1;for(i=0; i<pFormatCtx->nb_streams; i++)if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VI DEO){videoindex=i;break;}if(videoindex==-1){printf("Didn't find a video stream.\n");return -1;}pCodecCtx=pFormatCtx->streams[videoindex]->codec;pCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL){printf("Codec not found.\n");return -1;}if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){printf("Could not open codec.\n");return -1;}pFrame=av_frame_alloc();pFrameYUV=av_frame_alloc();//uint8_t *out_buffer=(uint8_t*)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));//avpicture_fill((AVPicture *)pFrameYUV, out_buffer,PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//SDL----------------------------if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {printf( "Could not initialize SDL - %s\n",SDL_GetError());return -1;}#if SHOW_FULLSCREENvi = SDL_GetVideoInfo();screen_w = vi->current_w;screen_h = vi->current_h;screen = SDL_SetVideoMode(screen_w, screen_h, 0,SDL_FULLSCREEN); #elsescreen_w = pCodecCtx->width;screen_h = pCodecCtx->height;screen = SDL_SetVideoMode(screen_w, screen_h, 0,0);#endifif(!screen) {printf("SDL: could not set video mode -exiting:%s\n",SDL_GetError());return -1;}bmp = SDL_CreateYUVOverlay(pCodecCtx->width,pCodecCtx->height,SDL_YV12_OVERLAY, screen);rect.x = 0;rect.y = 0;rect.w = screen_w;rect.h = screen_h;//SDL End------------------------packet=(AVPacket *)av_malloc(sizeof(AVPacket));//Output Information-----------------------------printf("------------- File Information ------------------\n");av_dump_format(pFormatCtx,0,filepath,0);printf("-------------------------------------------------\n"); #if OUTPUT_YUV420Pfp_yuv=fopen("output.yuv","wb+");#endifSDL_WM_SetCaption("Simplest FFmpeg Player",NULL);img_convert_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width,pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);//------------------------------while(av_read_frame(pFormatCtx, packet)>=0){if(packet->stream_index==videoindex){//Decoderet = avcodec_decode_video2(pCodecCtx, pFrame,&got_picture, packet);if(ret < 0){printf("Decode Error.\n");return -1;}if(got_picture){SDL_LockYUVOverlay(bmp);pFrameYUV->data[0]=bmp->pixels[0];pFrameYUV->data[1]=bmp->pixels[2];pFrameYUV->data[2]=bmp->pixels[1];pFrameYUV->linesize[0]=bmp->pitches[0];pFrameYUV->linesize[1]=bmp->pitches[2];pFrameYUV->linesize[2]=bmp->pitches[1];sws_scale(img_convert_ctx, (constuint8_t* const*)pFrame->data, pFrame->linesize, 0,pCodecCtx->height,pFrameYUV->data, pFrameYUV->linesize);#if OUTPUT_YUV420Pint y_size=pCodecCtx->width*pCodecCtx->height;fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Yfwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //Ufwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V#endifSDL_UnlockYUVOverlay(bmp);SDL_DisplayYUVOverlay(bmp, &rect);//Delay 40msSDL_Delay(40);}}av_free_packet(packet);}//FIX: Flush Frames remained in Codecwhile (1) {ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);if (ret < 0)break;if (!got_picture)break;sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);SDL_LockYUVOverlay(bmp);pFrameYUV->data[0]=bmp->pixels[0];pFrameYUV->data[1]=bmp->pixels[2];pFrameYUV->data[2]=bmp->pixels[1];pFrameYUV->linesize[0]=bmp->pitches[0];pFrameYUV->linesize[1]=bmp->pitches[2];pFrameYUV->linesize[2]=bmp->pitches[1];#if OUTPUT_YUV420Pint y_size=pCodecCtx->width*pCodecCtx->height;fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Yfwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //Ufwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V #endifSDL_UnlockYUVOverlay(bmp);SDL_DisplayYUVOverlay(bmp, &rect);//Delay 40msSDL_Delay(40);}sws_freeContext(img_convert_ctx);#if OUTPUT_YUV420Pfclose(fp_yuv);#endifSDL_Quit();//av_free(out_buffer);av_free(pFrameYUV);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0;}1.1版之后,新添加了一个工程:simplest_ffmpeg_player_su(SU版)。