ffmpeg 学习:002-代码架构
前言
使用 ffmpeg 库时,最好先理解好ffmpeg的代码结构图。
下面这张图表明了FFmpeg在解码一个视频的时候的函数调用流程,为了保证结构清晰,其中仅列出了最关键的函数,剔除了其它不是特别重要的函数。
多媒体处理基本流程
只有真正了解了多媒体处理的基本流程,研读 ffmpeg 源代码才能事半功倍。
下面分析一下多媒体中最基本最核心的视频解码过程,平常我们从网上下载一部电影或者一首歌曲,那么相应的多 媒体播放器为我们做好了一切工作,我们只用欣赏就 ok 了。目前几乎所有的主流多媒体播放器都是基于开源多媒 体框架 ffmpeg 来做的,可见 ffmpeg 的强大。下面是对一个媒体文件进行解码的主要流程:
A(Media file) --> B(Demux, 解复用)
B(解码, Decode) --> C(YUV/RGB, 数据)
解复用(Demux)
当我们打开一个多媒体文件之后,第一步就是解复用,称之为 Demux。为什么需要这一步,这一步究竟是做什么的?
我们知道在一个多媒体文件中,既包括音频也包括视频,而且音频和视频都是分开进行压缩的,因为音频和视频的压缩算法不一样,既然压缩算法不一样,那么肯定解码也不一样,所以需要对音频和视频分别进行解码。虽然音频和视频是分开进行压缩的,但是为了传输过程的方便,将压缩过的音频和视频捆绑在一起进行传输。所以我们解码的第一步就是将这些绑在一起的音频和视频流分开来,也就是传说中的解复用:所以一句话,解复用这一步就是将文件中捆绑在一起的音频流和视频流分开来以方便后面分别对它们进行解码。
解码(Decode)
这一步不用多说,一个多媒体文件肯定是经过某种或几种格式的压缩的,也就是通常所说的视频和音频编码,编码是为了减少数据量,否则的话对我们的存储设备是一个挑战,如果是流媒体的话对网络带宽也是一个几乎不可能完 成的任务。所以我们必须对媒体信息进行尽可能的压缩。
FFmpeg 中解码流程对应的 API 函数
了解了上面的一个媒体文件从打开到解码的流程,就可以很轻松的阅读 ffmpeg 代码,ffmpeg 的框架也基本是按照这个流程来的,但不是每个流程对应一个 API,下面这副图是我分析 ffmpeg 并根据自己的理解得到的 ffmpeg 解码 流程对应的 API,我想这幅图应该对理解 ffmpeg 和编解码有一些帮助。
A[Media file 容器] -->|avformat_open_input| B{Video Strems}
A[Media file 容器] --> C{Audio Strems}
A[Media file 容器] --> |demux|D{Subtitle Strems}
B{Video Strems} --> |av_read_frame| E[数据流的数据包]
E[数据流的数据包]-->|avcodec_decode_video2| 解码之后的视频帧
C{Audio Strems} --> F[音频流的数据包]
F[音频流的数据包]-->|avcodec_decode_audio4| 解码之后的音频帧
D{Subtitle Strems} --> G[字幕流的数据包]
G[字幕流的数据包]-->|avcodec_decode_subtitttle2,Decode| 解码之后的字幕
Ffmpeg 中 Demux 这一步是通过 avformat_open_input()这个 api 来做的,这个 api 读出文件的头部信息,并做 demux, 在此之后我们就可以读取媒体文件中的音频和视频流,然后通过 av_read_frame()从音频和视频流中读取出基本数据 流 packet,然后将 packet 送到 avcodec_decode_video2()和相对应的 api 进行解码。
流媒体数据流程讲解
FFMpeg 的 output_example.c 例子分析
该例子讲了如何输出一个 libavformat 库所支持格式的媒体文件。
(1)av_regis ter_all(),初始化 libavcodec 库,并注册所有的编解码器和格式。
(2)guess_form at(),根据文件名来获取输出文件格式,默认为 mpeg。
(3)av_alloc_form at_context()分配输出媒体内容。 ov->oform at = fm t; s nprintf( oc->filename, sizeof(oc->filename), “%s ”, filenam e );
(4)add_video_s tream ()使用默认格式的编解码器来增加一个视频流,并初始化编解码器。 (4.1)av_new_s tream ()增加一个新的流到一个媒体文件。
(4.2)初始化编解码器: c = s t->codec; c->codec_id = codec_id; c->codec_type = CODEC_TYPE_ VIDEO; c->bit_rate = 400000; c->width = 352; c->height = 288; c->tim e_base.den = STREAM_FR AME_RATE ; //每秒 25 副图像 c->tim e_base.num = 1; c->gop_size = 12; c->pix_fm t = STREAM_PIX_FMT; //默认格式为 P IX_FMT_ YUV420P …… ……
(5)av_s et_parameters ()设置输出参数,即使没有参数,该函数也必须被调用。
(6)dum p_form at()输出格式信息,用于调试。
(7)open_video()打开视频编解码器并分配必要的编码缓存。
(7.1)avcodec_find_encoder()寻找 c->codec_id 指定的视频编码器。
(7.2)avcodec_open()打开编码器。
(7.3)分配视频输出缓存: video_outbuf_s ize = 200000; video_outbuf = av_m alloc( video_outbuf_s ize );
(7.4)picture = alloc_picture()分配原始图像。
(7.4.1)avcodec_alloc_frame()分配一个 AVFram e 并设置默认值。
(7.4.2)s ize = avpicture_get_s ize()计算对于给定的图片格式以及宽和高,所需占用多少 内存。
(7.4.3)picture_buf = av_malloc( s ize )分配所需内存。
(7.4.4)avpicture_fill()填充 AVPicture 的域。
(7.5)可选。如果输出格式不是 YUV420P,那么临时的 YU V420P 格式的图像也是需要的,由 此再转换为 我们所需的格式,因此需要为临时的 YU V420P 图像分配缓存: tm p_picture = alloc_picture() 说明:tm p_picture,picture,video_outbuf。如果输出格式为 YUV420P,则直接通过 avcodec_ encode_video()函数将 picture 缓存中的原始图像编码保存到 video_outbuf 缓存中;如果输出格式不 是 YU V420P,则需要先通过 sws _s cale()函数,将 YUV420P 格式转换为目标格式,此时 tm p_picture 缓 存存放的是 YU V420P 格式的图像,而 picture 缓存为转换为目标格式后保存的图像,进而再将 picture 缓 存中的图像编码保存到 video_outbuf 缓存中。
(8)url_fopen()打开输出文件,如果需要的话。
(9)av_write_header()写流动头部。
(10)LOOP 循环{ 计算当前视频时间 video_pts 是否超时退出循环? write_video_fram e()视频编码 }
(10.1)write_video_frame() 如果图片不是 YU V420P,则需要用 sws _s cale()函数先进行格式转换。 若需要原始图像: av_init_packet()初始化一个包的选项域。 av_write_fram e()向输出媒体文件写一个包,该包会包含一个视频帧。 若需要编码图像: avcodec_encode_video()编码一视频帧。 av_init_packet() av_write_fram e()
(11)close_video()关闭每个编解码器。
(12)av_write_trailer()写流的尾部。
(13)释放资源 av_freep()释放 AVForm atContext 下的 AVS tream ->AVCodecContext 和 AVStream : for( i = 0; i < oc->nb_s treams ; i++ ){ av_freep( &oc->s treams [i]->codec ); av_freep( &oc->s treams [i] ); } url_fclose()关闭输出文件。 av_free()释放 AVForm atContext
ffmpeg 学习:002-代码架构的更多相关文章
- FFmpeg学习5:多线程播放视音频
在前面的学习中,视频和音频的播放是分开进行的.这主要是为了学习的方便,经过一段时间的学习,对FFmpeg的也有了一定的了解,本文就介绍了 如何使用多线程同时播放音频和视频(未实现同步),并对前面的学习 ...
- 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程
原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP ...
- JavaWeb学习之三层架构实例(三)
引言 通过上一篇博客JavaWeb学习之三层架构实例(二)我们基本上已经实现了对学生信息列表的增删改查操作(UI除外),但是不难看出,代码冗余度太高了,尤其是StudentDao这个类,其中的增删改查 ...
- ML平台_小米深度学习平台的架构与实践
(转载:http://www.36dsj.com/archives/85383)机器学习与人工智能,相信大家已经耳熟能详,随着大规模标记数据的积累.神经网络算法的成熟以及高性能通用GPU的推广,深度学 ...
- Libvirt代码架构
Libvirt介绍 参考资料 Libvirt学习 通过virsh了解libvirt api的调用方式 通过virHypervisorDriver了解libvirt api的实现 virsh代码阅读 通 ...
- (转)MyBatis框架的学习(二)——MyBatis架构与入门
http://blog.csdn.net/yerenyuan_pku/article/details/71699515 MyBatis框架的架构 MyBatis框架的架构如下图: 下面作简要概述: S ...
- FFmpeg 学习(五):FFmpeg 编解码 API 分析
在上一篇文章 FFmpeg学习(四):FFmpeg API 介绍与通用 API 分析 中,我们简单的讲解了一下FFmpeg 的API基本概念,并分析了一下通用API,本文我们将分析 FFmpeg 在编 ...
- FFmpeg 学习(七):FFmpeg 学习整理总结
一.FFmpeg 播放视频的基本流程整理 播放流程: video.avi(Container) -> 打开得到 Video_Stream -> 读取Packet -> 解析到 Fra ...
- 20145314郑凯杰 《Java程序设计》第2周学习总结 代码开始!
---恢复内容开始--- 20145314郑凯杰 <Java程序设计>第2周学习总结 代码开始! 教材学习内容总结 跟着教材的顺序开始总结我学过的内容: 1编辑.编译.运行教材上代码 这部 ...
- FFmpeg学习起步 —— 环境搭建
下面是我搭建FFmpeg学习环境的步骤. 一.在Ubuntu下 从http://www.ffmpeg.org/download.html下载最新的FFmpeg版本,我的版本是ffmpeg-2.7.2. ...
随机推荐
- 电子书及阅读器Demo
电子书阅读器(Kindle,电子纸技术.LCD.电子墨水技术等: 亚马逊/当当网站) 电子书产业可分5大环节:内容供应商.数字格式制作商.内容流通服务平台.传输平台以及终端阅读器产品. 全球电子书市 ...
- 中国5G,如何避免重复投资?
前不久,工信部正式向中国移动.中国联通.中国电信发放5G商用牌照,此举意味着中国提前启动5G商用计划,随之而来的,将会是运营商.设备商大规模的投资.相关数据机构预测,三大运营商2019年预计会投入30 ...
- ubuntu 16.04 XDRP实现Windows远程访问
如何通过XDRP实现Windows远程访问 下面才是本文的重点,本文主要是讲xrdp在目前最新版Ubuntu 16.04下,如果实现Windows远程访问.网上也很多相关教程,但是都需要安装xfac4 ...
- javaweb项目中web.xml配置文件的/和/*的区别
1.拦截"/",可以实现现在很流行的REST风格.很多互联网类型的应用很喜欢这种风格的URL.为了实现REST风格,拦截了所有的请求.同时对*.js,*.jpg等静态文件的访问也就 ...
- java 操作 csv文件
CSV是逗号分隔文件(Comma Separated Values)的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格或数据库软件.在 CSV文件中,数据“栏”以逗号分隔,可允许程序通 ...
- 如何在PHP中防止SQL注入
使用PDO对象(对于任何数据库驱动都好用) addslashes用于单字节字符串的处理, 多字节字符用mysql_real_escape_string吧. 另外对于php手册中get_magic_qu ...
- 女神说拍了一套写真集想弄成素描画?很简单,用Python就行了!
素描作为一种近乎完美的表现手法有其独特的魅力,随着数字技术的发展,素描早已不再是专业绘画师的专利,今天这篇文章就来讲一讲如何使用python批量获取小姐姐素描画像.文章共分两部分: 第一部分介绍两种使 ...
- ERROR: but there is no YARN_RESOURCEMANAGER_USER defined. Aborting operation.
将start-dfs.sh,stop-dfs.sh两个文件顶部添加以下参数 HDFS_NAMENODE_USER=root HDFS_DATANODE_USER=root HDFS_SECONDARY ...
- jsp 防止表单多次提交
1:首先java 后台代码生成一个token,然后保存到jsp 页面的一个隐藏控件并且保存到set session中 */ @RequestMapping("/yuDengJi") ...
- centos6.5安装图形操作界面
yum -y install xorg-x11-fonts-Type1 #安装Xwindow yum -y groupinstall "X Window System" #安装GN ...