没有合适的资源?快使用搜索试试~ 我知道了~
FFMPEG教程完美教程
5星 · 超过95%的资源 需积分: 50 446 下载量 12 浏览量
2014-09-25
09:29:04
上传
评论 18
收藏 968KB PDF 举报
温馨提示
试读
56页
老外写的用ffplay流程来讲解ffmpeg库用法的书,由浅入深,非常好,国内高手翻译成中文,本人又再次进行了仔细的排版校对,并对代码着色,希望对大家有用。各位朋友验收后给5星好评哦,谢谢!
资源推荐
资源详情
资源评论
1 / 56
FFPLAY 的原理
目录
概要 ............................................................................................................................................................. 2
打开文件 ..................................................................................................................................................... 2
保存数据 ..................................................................................................................................................... 4
读取数据 ..................................................................................................................................................... 5
输出到屏幕 .................................................................................................................................................. 8
创建一个显示 .............................................................................................................................................. 9
显示图像 ..................................................................................................................................................... 9
绘制图像 ................................................................................................................................................... 10
播放声音 ................................................................................................................................................... 12
设置音频 ................................................................................................................................................... 12
队列 ........................................................................................................................................................... 14
意外情况 ................................................................................................................................................... 17
为队列提供包 ............................................................................................................................................ 18
取出包 ....................................................................................................................................................... 18
最后解码音频 ............................................................................................................................................ 20
创建线程 ................................................................................................................................................... 21
得到帧:video_thread .............................................................................................................................. 27
把帧队列化 ................................................................................................................................................ 28
显示视频 ................................................................................................................................................... 32
如何同步视频 ............................................................................................................................................ 35
同步 ........................................................................................................................................................... 36
写代码:获得帧的时间戳 .......................................................................................................................... 37
写代码:使用 PTS 来同步 ........................................................................................................................ 39
同步:声音时钟 ........................................................................................................................................ 42
同步音频 ................................................................................................................................................... 44
提取时钟 ................................................................................................................................................... 45
同步音频 ................................................................................................................................................... 46
修正样本数 ................................................................................................................................................ 48
快进快退 ................................................................................................................................................... 49
清空我们的缓冲 ........................................................................................................................................ 52
软件缩放 ................................................................................................................................................... 54
现在还要做什么? ..................................................................................................................................... 56
2 / 56
概要
电影文件有很多基本的组成部分。首先,文件本身被称为容器 Container,容器的类型决定了信息被
存放在文件中的位置。AVI 和 Quicktime 就是容器的例子。接着,你有一组流,例如,你经常有的是一个
音频流和一个视频流。(一个流只是一种想像出来的词语,用来表示一连串的通过时间来串连的数据元素)。
在流中的数据元素被称为帧 Frame。每个流是由不同的编码 器来编码生成的。编解码器描述了实际的数
据是如何被编码 Coded 和解码 DECoded 的,因此它的名字叫做 CODEC。Divx 和 MP3 就是编解码器的
例子。接着从流中被读出来的叫做包 Packets。包是一段数据,它包含了一段可以被解码成方便我们最后
在应用程序中操作的原始帧的数据。根据我们的目的,每个包包含了完整的帧或者对于音频来说是许多格
式的完整帧。
基本上来说,处理视频和音频流是很容易的:
10 从 video.avi 文件中打开视频流 video_stream
20 从视频流中读取包到帧中
30 如果这个帧还不完整,跳到 20
40 对这个帧进行一些操作
50 跳回到 20
在这个程序中使用 ffmpeg 来处理多种媒体是相当容易的,虽然很多程序可能在对帧进行操作的时候
非常的复杂。因此在这篇指导中,我们将打开一个文件,读取里面的视频流,而且我们对帧的操作将是把
这个帧写到一个 PPM 文件中。
打开文件
首先,来看一下我们如何打开一个文件。通过 ffmpeg,你必需先初始化这个库。(注意在某些系统中
必需用<ffmpeg/avcodec.h>和<ffmpeg/avformat.h>来替换)
#include <avcodec.h>
#include <avformat.h>
...
int main(int argc, charg *argv[])
{
av_register_all();
这里注册了所有的文件格式和编解码器的库,所以它们将被自动的使用在被打开的合适格式的文件
上。注意你只需要调用 av_register_all()一次,因此我们在主函数 main()中来调用它。如果你喜欢,也可
以只注册特定的格式和编解码器,但是通常你没有必要这样做。
3 / 56
现在我们可以真正的打开文件:
AVFormatContext *pFormatCtx;
// Open video file
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
return -1; // Couldn't open file
我们通过第一个参数来获得文件名。这个函数读 取 文 件 的 头 部 并 且 把信息保存到我们 给 的
AVFormatContext 结构体中。最后三个参数用来指定特殊的文件格式,缓冲大小和格式参数,但如果把它
们设置为空 NULL 或者 0,libavformat 将自动检测这些参数。
这个函数只是检测了文件的头部,所以接着我们需要检查在文件中的流的信息:
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
return -1; // Couldn't find stream information
这个函数为 pFormatCtx->streams 填充上正确的信息。我们引进一个手工调试的函数来看一下里面有什
么:
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, argv[1], 0);
现在 pFormatCtx->streams 仅仅是一组大小为 pFormatCtx->nb_streams 的指针,所以让我们先跳过
它直到我们找到一个视频流。
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
}
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
流中关于编解码器的信息就是被我们叫做"codec context"(编解码器上下文)的东西。这里面包含了
4 / 56
流中所使用的关于编解码器的所有信息,现在我们有了一个指向他的指针。但是我们必需要找到真正的编
解码器并且打开它:
AVCodec *pCodec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
{
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
}
// Open codec
if(avcodec_open(pCodecCtx, pCodec)<0)
return -1; // Could not open codec
有些人可能会从旧的指导中记得有两个关于这些代码其它部分:添加 CODEC_FLAG_TRUNCATED
到 pCodecCtx->flags 和添加一个 hack 来粗糙的修正帧率。这两个修正已经不在存在于 ffplay.c 中。因此,
我必需假设它们不再必 要。我们移除了那些代码后还有一个需要指出的不同点:pCodecCtx->time_base
现在已经保存了帧率的信息。time_base 是一个结构体,它里面有一个分子和分母 (AVRational)。我们使
用分数的方式来表示帧率是因为很多编解码器使用非整数的帧率(例如 NTSC 使用 29.97fps)。
保存数据
现在我们需要找到一个地方来保存帧:
AVFrame *pFrame;
// Allocate video frame
pFrame=avcodec_alloc_frame();
因为我们准备输出保存 24 位 RGB 色的 PPM 文件,我们必需把帧的格式从原来的转换为 RGB。
FFMPEG 将为我们做这些转换。在大多数项目中(包括我们的这个)我们都想把原始的帧转换成一个特
定的格式。让我们先为转换来申请一帧的内存。
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
5 / 56
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) );
av_malloc 是 ffmpeg 的 malloc,用来实现一个简单的 malloc 的包装,这样来保证内存地址是对齐的
(4 字节对齐或者 2 字节对齐)。它并不能保护你不被内存泄漏,重复释放或者其它 malloc 的问题所困扰。
现在我们使用 avpicture_fill 来把帧和我们新申请的内存来结合。关于 AVPicture 的结成:AVPicture
结构体是 AVFrame 结构体的子集――AVFrame 结构体的开始部分与 AVPicture 结构体是一样的。
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset of AVPicture
avpicture_fill( (AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height );
最后,我们已经准备好来从流中读取数据了。
读取数据
我们将要做的是通过读取包来读取整个视频流,然后把它解码成帧,最好后转换格式并且保存。
int frameFinished;
AVPacket packet;
i=0;
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);
剩余55页未读,继续阅读
zdzlc
- 粉丝: 0
- 资源: 3
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Python 版冒泡排序算法源代码
- tensorflow-gpu-2.7.2-cp38-cp38-manylinux2010-x86-64.whl
- tensorflow-2.7.3-cp39-cp39-manylinux2010-x86-64.whl
- tensorflow-2.7.2-cp39-cp39-manylinux2010-x86-64.whl
- Python版本快速排序源代码
- Python 语言版的快速排序算法实现
- 450815388207377安卓_base.apk
- 超微主板 X9DRE-TF+ bios 支持 nvme启动
- 基于Python通过下载气象数据和插值拟合离散数据曲线实现对寒潮过程的能量分析
- 智能车仿真软件.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
前往页