教程原地址为:http://dranger.com/ffmpeg/tutorial01.html,本人只是做了翻译和部分接口更新工作,保证其能正常工作。需要做一些预备工作
:::java sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libavdevice-dev libavfilter-dev libavutil-dev libpostproc-dev 首先我们需要了解视频文件的一些基本概念,视频文件本身被称作容器,例如avi或者是quicktime,容器的类型确定了文件的信息。然后,容器里装的东西叫流(stream),通常包括视频流和音频流(“流”的意思其实就是“随着时间推移的一段连续的数据元素”)。流中的数据元素叫做“帧”。每个流由不同的编解码器来编码,编解码器定义了数据如何编码(COded)和解码(DECoded),所以叫做编解码器(CODEC)。编解码器的例子有Divx和mp3。包(Packets),是从流中读取的,通过解码器解包,得到原始的帧,我们便可以对这些数据进行播放等的处理。对于我们来说,每个包包含完整的帧,或者多个音频帧。
在初级的水平,处理音视频流是非常简单的:
从video.avi中获得视频流 从视频流中解包得到帧 如果帧不完整,重复第2步 对帧进行相关操作 重复第2步 用ffmpeg来处理多媒体就像上面的步骤那么简单,即使你的第4步可能很复杂。所以在本教程,我们先打开一个视频,读取视频流,获得帧,然后第4步是把帧数据存储为PPM文件。
##打开文件
我们先来看一下怎么打开一个视频文件,首先把头文件包含进来
:::c #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> ... int main(int argc, char *argv[]){ av_register_all(); av_register_all只需要调用一次,他会注册所有可用的文件格式和编解码库,当文件被打开时他们将自动匹配相应的编解码库。如果你愿意,可以之注册个别的文件格式和编解码库。
现在我们真的要打开一个文件了
:::c AVFormatContext *pFormatCtx; if(av_open_input_file(&pFormatCtx,argv[1],NULL,0,NULL)!=0) return -1; 我们从传入的第一个参数获得文件路径,这个函数会读取文件头信息,并把信息保存在我们存入的pFormatCtx结构体当中。这个函数后面三个参数分别是指定文件格式,缓存大小,和格式化选项,当我们设置为NULL或0时,libavformat会自动完成这些工作。
这个函数仅仅是获得了头信息,下一步我们要得到流信息
:::c if(av_find_steam_info(pFormatCtx)<0) return -1 这个函数填充了pFormatCtx->streams流信息,
我们可以通过dump_format把信息打印出来
:::c dump_format(pFormatCtx, 0, argv[1], 0); pFromatCtx->streams只是大小为pFormateCtx->nb_streams的一系列的点,我们要从中得到视频流
:::c int i; AVCodecContext *pCodecCtx; // Find the first video stream videoStream=-1; for(i=0; i<pformatctx->nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } if(videoStream==-1) return -1; // Didn't find a video stream</pformatctx-></pre> // Get a pointer to the codec context for the video stream pCodecCtx=pFormatCtx->streams[videoStream]->codec; pCodecCtx包含了这个流在用的编解码的所有信息,但我们仍需要通过他获得特定的解码器然后打开他。...