ffmpeg初次学习(仅针对编码)
学习资源
官方文档: Documentation
雷神博客
可移步 [总结]FFMPEG视音频编解码零基础学习方法
结构体学习:FFMPEG结构体分析
基础知识
视频编码
视频编码的主要作用是将视频像素数据(RGB,YUV等)压缩成为视频码流,从而降低视频的数据量。不压缩就视频就太大了。
主要视频编码
名称 | 推出机构 |
---|---|
HEVC(H.265) | MPEG/ITU-T |
H.264 | MPEG/ITU-T |
MPEG4 | MPEG |
MPEG2 | MPEG |
VP9 | |
VP8 | |
VC-1 | Microsoft Inc. |
优劣关系
HEVC(H.265) > VP9 > H.264 > VP8 > MPEG4 > H.263 > MPEG2
结构体学习
AVFrame 结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息
AVCodecContext 是FFmpeg编解码上下文的结构体,而AVCodec是编解码参数的结构体
AVPacket 是存储压缩编码数据相关信息的结构体
AVCodec是存储编解码器信息的结构体
结构体关系
每个AVStream存储一个视频/音频流的相关数据;每个AVStream对应一个AVCodecContext,存储该视频/音频流使用解码方式的相关数据;
每个AVCodecContext中对应一个AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个AVCodec结构。
官方demo之encode.c学习理解
学习官方demo:encode_video.c
我自己对官方demo进行了修改并加了注释,修改后的文件可直接运行,已上传至 资源下载地址
流程分析:
- 程序运行后给定输出的文件路径
- 调用
avcodec_find_encoder
查找编码器 AVCodec - 调用
avcodec_alloc_context3
分配编码器上下文 AVCodecContext - 调用
av_packet_alloc
分配 AVPacket,编码器会将每个AVFrame编码为AVPacket - 给 AVCodecContext 配置参数,如码率、视频宽高、帧格式等等
- 调用
avcodec_open2
打开编码器 - 调用
av_frame_alloc
分配 AVFrame 内存并设置帧的格式和宽高 - 调用
av_frame_get_buffer
分配帧数据使用的空间 - 开始for循环,首先调用
av_frame_make_writable
确保帧数据 AVFrame 可写,然后准备一帧虚拟图像数据写入frame->data
,最后给每帧的pts赋值,告诉播放器在什么时候显示这一帧数据 - 开始编码,调用
avcodec_send_frame
把帧数据 AVFrame 发送给编码器 - 调用
avcodec_receive_packet
把编码后的帧 AVPacket 从编码器取出,然后把编码后的每一帧写入输出文件 File ,写完后调用av_packet_unref
解除对 AVPacket 的引用 - 如果编码器ID是MPEG,需要向输出文件 File 的结尾添加一个固定序列从而得到一个真正的MPEG文件
- 最后关闭文件 File,并释放 AVCodecContext、AVFrame、AVPacket 占用的内存,调用
avcodec_free_context
、av_frame_free
、av_packet_free
API学习
avcodec_find_encoder
根据一个AVCodecID找到一个注册的编码器
const AVCodec *avcodec_find_encoder(enum AVCodecID id);
常见 AVCodecID 随便列举一些
enum AVCodecID {AV_CODEC_ID_NONE,/* video codecs */AV_CODEC_ID_H263,AV_CODEC_ID_MPEG4,AV_CODEC_ID_H264, AV_CODEC_ID_HEVC,
}
实例:
const AVCodec *codec;
enum AVCodecID codec_id;codec_id = AV_CODEC_ID_HEVC;codec = avcodec_find_encoder(codec_id);
if (!codec) {printf("Codec '%d' not found\n", codec_id);exit(1);
}
avcodec_alloc_context3
为 AVCodecContext
结构体分配内存,并将各字段设置为默认值,结果返回的结构体需要使用 avcodec_free_context()
进行释放内存
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
实例:
AVCodecContext *c= NULL;const AVCodec *codec;c = avcodec_alloc_context3(codec);if (!c) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);}.........avcodec_free_context(&c);
av_packet_alloc
为 AVPacket
结构体分配内存,并将各字段设置为默认值,结果返回的结构体需要使用 av_packet_free()
进行释放内存
AVPacket *av_packet_alloc(void);
实例:
AVPacket *pkt;pkt = av_packet_alloc();if (!pkt)exit(1);......... av_packet_free(&pkt);
avcodec_open2
初始化 AVCodecContext
以使用给定的 AVCodec
,使用此函数之前需要使用 avcodec_alloc_context3()
分配内存
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
av_frame_get_buffer
分配新的buffers给视频数据
在调用该函数之前需要设置 frame 的一些参数format、width、height
int av_frame_get_buffer(AVFrame *frame, int align);
参数 align
强烈推荐设置为0,系统会根据当前CPU自动设置alignment
实例:
AVFrame *frame;frame = av_frame_alloc();frame->format = c->pix_fmt;frame->width = c->width;frame->height = c->height;av_frame_get_buffer(frame, 32);
avcodec_send_frame
发送数据帧到编码器。使用 avcodec_receive_packet()
函数来检索缓冲输出数据包
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
avcodec_receive_packet
从编码器读取编码好的数据
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
返回类型:
0 表示成功
AVERROR(EAGAIN) 输出当前不可用,用户必须给予输入
AVERROR_EOF 编码器被完全冲洗,不再会有输出的 packets
AVERROR(EINVAL) codec没有开启,或者它是一个解码器而非编码器
实例:
ret = avcodec_receive_packet(enc_ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if (ret < 0) {fprintf(stderr, "Error during encoding\n");exit(1);}
结束语
刚开始学ffmpeg,摸着石头过河,一点一点看demo和源码还是蛮有意思的
英文阅读有待提高,要不然看不懂开发者给的注释
ffmpeg初次学习(仅针对编码)相关推荐
- 使用FFMPEG——4.2.2版本实现提取视频编码解码文件,ffmpeg基础学习。
FFMPEG基础学习 视频解码,并且输出到文件. 我通过雷霄骅的博客学习FFMPEG,在学习过程中发现"雷神"的代码由于版本的问题,很多代码已经无法在FFMPEG--4.2.2版本 ...
- FFmpeg再学习 -- FFmpeg解码知识
继续看雷霄骅的 课程资料 - 基于FFmpeg+SDL的视频播放器的制作 前面用了五个篇幅来讲 FFmpeg,其主要目的是为实现将图片转视频的功能. 总的来说,对于 FFmepg 多少有一些了解了.但 ...
- mp4v2再学习 -- H264视频编码成MP4文件
一.H264视频编码成MP4文件 参看:H264视频编码成MP4文件 参看:mp4v2在VS2010下的编译与在项目中的使用 最近做项目需要将H264文件封装为mp4文件,从网上找到了MP4V2库,下 ...
- FFmpeg深度学习模块的历史、现状和计划
本文来自英特尔资深图形图像软件工程师 郭叶军在LiveVideoStack线上分享的内容,详细介绍了FFmpeg中深度学习模块的历史.现状及未来计划,并针对深度学习模块总体架构与代码实践做详细解析. ...
- FFmpeg再学习 -- 硬件加速编解码
为了搞硬件加速编解码,用了一周时间来看 CUDA,接下来开始加以总结. 一.什么是 CUDA (1)首先需要了解一下,什么是 CUDA. 参看:百度百科 -- CUDA 参看:CUDA基础介绍 参看: ...
- FFmpeg再学习 -- Windows下安装说明
看了半晌 雷霄骅 的 ffmpeg 的视频.待续稍后总结. 一.FFmpeg 简介 FFmpeg 是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用 LGPL 或GPL 许可证(依据你选择的组 ...
- 最简单的基于FFMPEG的视频编码器(YUV编码为H.264)
===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...
- 【LiveVideoStack线上分享】FFmpeg深度学习模块架构与代码实践
FFmpeg可谓是音视频开发中的一把瑞士军刀,其中filter提供了很多音视频特效与图像处理的功能,除了传统的FFmpeg+OpenGL/OpenCV以外,深度学习模块提供了一种新的方式.本周四晚19 ...
- 深度学习赋能视频编码
深度学习赋予了诸如计算机视觉等领域新的研究契机,其应用也获得了视频编码领域的诸多关注.在LiveVideoStack线上分享中北京大学信息技术学院 助理研究员王苫社详细介绍了当下深度学习在视频编码中的 ...
最新文章
- linux 逻辑卷扩展
- WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换
- Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round) A. Basic Diplomacy
- javascript 运算符优先级
- win10 安装mysql 8.0.12
- 五子棋的禁手c++语言实现,C++实现简单五子棋游戏
- UIKit框架类层次图
- Maven配置文件无法被导出或者生效的问题【已解决】
- python复杂网络库networkx:基础
- php单例模式的实现方式,PHP之单例模式的实现
- 电脑必备必装的软件工具神器,强烈推荐
- undo和redo日志
- 报道|香港科大校友“盐马行”活动成功举办
- 数据结构严蔚敏--综述
- 【嵌入式系统】STM32时钟系统+时钟配置函数解析
- protel 二极管正负极怎么看
- R语言绘图:条形图——barplot
- winsock和winsock2冲突
- html5侧匡下拉注释,可圈可点网资料
- CANoe软件之离线数据分析