FFmpeg 基本操作摘要(一) (转流、解码、编码)
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=061)
本文发布于 2018-05-11 15:47:25,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=061)
环境说明
无
前言
近一段时间来,自己的主要工作都在是在做数据源端(设备端)音视频传输、编解码相关的事情,于是逐渐又和FFmpeg打上了交到,用到了其中的一些常见的内容,同时也解决了一些不常见的事情。
同时这里表达对“”“”雷神“”“”的敬意(一路走好,雷神),其blog上相关的FFmpeg教程是我学习FFmpeg的启蒙教程,其的blog可以不夸张的说,是国内非常非常非常好非常非常非常好非常非常非常好的音视频相关入门教程了,建议搞音视频的人可以多参考。这里提供一个链接指向雷神的博客地址,供大家参考(需从零学习FFmpeg,请参考其FFmpeg专栏):https://blog.csdn.net/leixiaohua1020
FFmpeg 相关内容简介
FFmpeg常用结构体
AVFormatContext
//Format I/O context.(FFmpeg中的IO流的格式容器,具体来说就是用来记录打开的流的格式相关信息,列如:记录打开的rtsp流中的音视频流格式信息、MP4
文件的流格式信息等等)
AVCodecContext //FFmpeg中记录编码器相关信息的容器
AVCodec //FFmpeg 中编码器容器
AVFrame //This structure describes decoded (raw) audio or video data.(FFmpeg中用于描述裸音视频数据的容器,列如:视频中的YUV数据,音频中的PCM数据)
AVPacket // This structure stores compressed data. It is typically exported by demuxers
//and then passed as input to decoders, or received as output from encoders and
//then passed to muxers.(此结构体用于描述音视频编码后的数据,主要用在把编码后的数据送入解码器或者接收编码器输出的数据,列如:视频中的H264数据, 音频中的:G711A数据)
SwsContext //图像缩放和变换的关键容器
FFmpeg中常见调用
void av_register_all(void); // Initialize libavformat and register all the muxers, demuxers and
// protocols. If you do not call this function, then you can select
// exactly which formats you want to support.
//FFmpeg 中用于初始化libavformat 库,注册音视频复用器,各种协议等等。 这里需要注意的是,许多没有用到了内容都注册了,可能造成浪费,若需要指定注册哪些内容,可参考av_register_output_format()、av_register_input_format()
int avformat_network_init(void); //此函数用于初始化网络相关的组件,列如:你要解析RTSP流,需要先调用此函数
/**
* Do global initialization of network components. This is optional,
* but recommended, since it avoids the overhead of implicitly
* doing the setup for each session.
*
* Calling this function will become mandatory if using network
* protocols at some major version bump.
*/
AVFormatContext *avformat_alloc_context(void); //为AVFormatContext分配空间
void avformat_free_context(AVFormatContext *s); //释放AVFormatContext空间
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);//Open an input stream and read the header.
int avio_open(AVIOContext **s, const char *url, int flags); // 用于初始化AVIOContext,此结构体用于文件的读写操作
//* Create and initialize a AVIOContext for accessing the
//* resource indicated by url.
int avio_close(AVIOContext *s); //释放一个AVIOContext对象
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); //读取流数据,分析流信息
//Read packets of a media file to get stream information.
void av_dump_format(AVFormatContext *ic,
int index,
const char *url,
int is_output);//就是打印一下AVFormatContext 里面存放的一些我们关心的信息
/*
* Print detailed information about the input or output format, such as
* duration, bitrate, streams, container, programs, metadata, side data,
* codec and time base.
*/
AVCodec *avcodec_find_decoder(enum AVCodecID id);查找一个解码器
//Find a registered decoder with a matching codec ID.
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);//初始化一个编码器,初始化此结构体AVCodecContext
/*
* Initialize the AVCodecContext to use the given AVCodec. Prior to using this
* function the context has to be allocated with avcodec_alloc_context3().
*/
int avcodec_close(AVCodecContext *avctx);//释放AVCodecContext 空间
int av_read_frame(AVFormatContext *s, AVPacket *pkt);//返回下一帧,数据(编码后的数据)存放到pkt里面,这里会给AVPacket 分配空间,此处一定要释放,否则将会发生内存泄漏
//Return the next frame of a stream.
int av_new_packet(AVPacket *pkt, int size);//给AVPacket buf成员分配空间,同理上文
/*
* Allocate the payload of a packet and initialize its fields with
* default values.
*/
void av_free_packet(AVPacket *pkt);//释放AVPacket
AVFrame *av_frame_alloc(void);//申请AVFrame空间
void av_frame_free(AVFrame **frame);//释放AVFrame空间
void *av_malloc(size_t size);//ffmpeg中申请一定大小的内存空间
void av_free(void *ptr);//释放空间
//av_malloc av_free是对malloc和free的封装,本质就是基础内存操作
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
int dstW, int dstH, enum AVPixelFormat dstFormat,
int flags, SwsFilter *srcFilter,
SwsFilter *dstFilter, const double *param);//创建一个指定大小和颜色空间的SwsContext
/*
* Allocate and return an SwsContext. You need it to perform
* scaling/conversion operations using sws_scale().
*/
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
const int srcStride[], int srcSliceY, int srcSliceH,
uint8_t *const dst[], const int dstStride[]);//根据指定SwsContext ,来对原始图像进行变换
/*
* Scale the image slice in srcSlice and put the resulting scaled
* slice in the image in dst. A slice is a sequence of consecutive
* rows in an image.
*/
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
const AVPacket *avpkt);//对一帧数据进行解码
/ * Decode the video frame of size avpkt->size from avpkt->data into picture.
* Some decoders may support multiple frames in a single AVPacket, such
* decoders would then just decode the first frame.
* /
int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr);//对一帧数据进行编码
FFmpeg中需要注意的事项
FFmpeg中除了正常使用外,需要我们注意的就是内存泄漏的问题了。
这里我们需要关注几个问题:
/*
对于以下的结构体,一定要重点关注,申请了内存,一定要释放,否则在循环调用一些内容时,一定会发生内存泄漏。
AVFormatContext
AVCodecContext
AVCodec
AVFrame
AVPacket
其中我们需要核心关注AVPacket这个结构体,这个结构体很容易让我们懵逼,出现内存泄漏。
av_read_frame
av_new_packet
上面两个都会申请内存,需要我们释放内存
av_free_packet
av_packet_unref
由于AVPacket 设计为缓冲区计数的方式,实现了一定的数据共享,方便FFmpeg管理内存,但是这里也给我们埋下了地雷:那就是AVPacket的生命周期就不好确定了,因为你调用了以上的函数,而内存不一定释放了。关于AVPacket还有许多函数,比如av_copy_packet、av_packet_ref、av_init_packet等,使用它们一定要小心,如果需要深入研究,建议查看它们的源码,这样就能够对这些调用有了更深刻的理解。
*/
这里我再多说一句:由于FFmpeg2 和FFmpeg3有巨大的区别,很多东西也发生了变化,网上的教程很多是FFmpeg3以后的,使用的时候需要注意。同时,FFmpeg真的一不留神就发生内存泄漏了,需要我们注意。
FFmpeg 使用的一般流程
解码过程
av_register_all
avformat_network_init
avformat_alloc_context//初始化AVFormatContext
avformat_open_input //打开流
avformat_find_stream_info //读取流信息
avcodec_find_decoder //根据上调用来确定编码器id,然后来查找相关编码器
avcodec_open2 //打开编码器,初始化AVCodecContext
av_read_frame //读取一帧压缩数据
avcodec_decode_video2 //解压一帧数据
sws_scale //数据转换
//后续对原始音视频数据进行相关处理
编码过程
av_register_all
avformat_network_init
avformat_alloc_context
avio_open
avformat_new_stream
//这里通过相关方法把原始音视频数据准备好
avcodec_find_decoder //根据上调用来确定编码器id,然后来查找相关编码器
avcodec_open2 //打开编码器,初始化AVCodecContext
avcodec_encode_video2 //编码
//后续处理编码后的事情
转流过程
av_register_all
avformat_network_init
avformat_alloc_context//初始化AVFormatContext
avformat_open_input //打开流
avformat_find_stream_info //读取流信息
avcodec_find_decoder //根据上调用来确定编码器id,然后来查找相关编码器
avcodec_open2 //打开编码器,初始化AVCodecContext
av_read_frame //读取一帧压缩数据
//这里对av_read_frame 中的pkt data数据域和size数据域进行处理即可
后记
无
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)

PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
FFmpeg 基本操作摘要(一) (转流、解码、编码)的更多相关文章
- VS2015编译FFMPEG,修改FFmpeg缓冲区大小解决实时流解码丢包问题,FFmpeg错误rtsp流地址卡死的问题,设置超时
之前尝试过很多网上利用Windows编译FFmpeg的文章,都没有办法编译X64位的FFmpeg,有些教程中有专门提到编译64位的FFmpeg需要下载mingw-w64-install,但是编译的过程 ...
- FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库
FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:1. 安装faad2 # wget http://downloads.sourceforge.net/fa ...
- FFmpeg再学习 -- 硬件加速编解码
为了搞硬件加速编解码,用了一周时间来看 CUDA,接下来开始加以总结. 一.什么是 CUDA (1)首先需要了解一下,什么是 CUDA. 参看:百度百科 -- CUDA 参看:CUDA基础介绍 参看: ...
- ffmpeg protocol concat 进行ts流合并视频的时间戳计算及其音画同步方式一点浅析
ffmpeg protocol concat 进行ts流合并视频的时间戳计算及音画同步方式一点浅析 目录 ffmpeg protocol concat 进行ts流合并视频的时间戳计算及音画同步方式一点 ...
- 基于ffmpeg的简单音视频编解码的例子
近日需要做一个视频转码服务器,对我这样一个在该领域的新手来说却是够我折腾一番,在别人的建议下开始研究开源ffmpeg项目,下面是在代码中看到的一 段例子代码,对我的学习非常有帮助.该例子代码包含音频的 ...
- TS 流解码过程
TS 流解码过程: 1. 获取TS中的PAT 2. 获取TS中的PMT 3. 根据PMT可以知道当前网络中传输的视频(音频)类型(H264),相应的PID,PCR的PID等信息. 4. 设置demux ...
- 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))
===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...
- javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转换为YUV、BGR24或RGB24等图像像素数据
javacpp-ffmpeg系列: javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片 javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转 ...
- javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片
javacpp-ffmpeg系列: javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片 javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转 ...
- TS流解码过程-ES-PES-PTS-DTS
转载自http://blog.chinaunix.net/uid-9688646-id-1998407.html TS 流解码过程: 1. 获取TS中的PAT 2. 获取TS中的PMT 3. 根据PM ...
随机推荐
- korean doll likeness模型|Japanese-doll-likeness模型获取及使用
1.模型 之前给大家写了Mac安装stable-diffusion-webui绘制AI妹子保姆级教程,教程在下面 [奶奶看了也不会]AI绘画 Mac安装stable-diffusion-webui绘制 ...
- Spring Boot 跨域的问题
- .NET 云原生架构师训练营(模块二 基础巩固 EF Core 查询)--学习笔记
2.4.5 EF Core -- 查询 关联数据加载 客户端与服务端运算 跟踪与不跟踪 复杂查询运算 原生 SQL 查询 全局查询筛选器 关联数据加载 学员和助教都在项目分组中,调整模型,删除 Ass ...
- 《ASP.ENT Core 与 RESTful API 开发实战》-- (第6章)-- 读书笔记(上)
第 6 章 高级查询和日志 6.1 分页 在 EF Core 中,数据的查询通过集成语言查询(LINQ)实现,它支持强类型,支持对 DbContext 派生类的 DbSet 类型成员进行访问,DbSe ...
- NC20115 [HNOI2015]菜肴制作
题目链接 题目 题目描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号 ...
- NC24734 [USACO 2010 Mar G]Great Cow Gathering
题目链接 题目 题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, ...
- python第五章pta习题总结
四.编程部分 1.sorted函数: sorted(iterable, cmp=None, key=None, reverse=False) #iterable:可迭代的对象 #cmp:比较规则 #k ...
- http 与 tcp 的一些学习
HTTP 是一个基于 TCP/IP 通信协议来传递数据的协议,传输的数据类型为 HTML 文件,.图片文件, 查询结果等. HTTP 协议一般用于 B/S 架构().浏览器作为 HTTP 客户端通过 ...
- C++中两种获取UUID的方法(编程)
第一种,依托WMI #define _WIN32_DCOM #include <iostream> using namespace std; #include <comdef.h&g ...
- go经典知识及总结
1.无论sync.Mutex还是其衍生品都会提示不能复制,但是能够编译运行 加锁后复制变量,会将锁的状态也复制,所以 mu1 其实是已经加锁状态,再加锁会死锁. 所以此题的答案是 fatal erro ...