学习资源

官方文档: Documentation

雷神博客
可移步 [总结]FFMPEG视音频编解码零基础学习方法

结构体学习:FFMPEG结构体分析

基础知识

视频编码

视频编码的主要作用是将视频像素数据(RGB,YUV等)压缩成为视频码流,从而降低视频的数据量。不压缩就视频就太大了。

主要视频编码

名称 推出机构
HEVC(H.265) MPEG/ITU-T
H.264 MPEG/ITU-T
MPEG4 MPEG
MPEG2 MPEG
VP9 Google
VP8 Google
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进行了修改并加了注释,修改后的文件可直接运行,已上传至 资源下载地址

流程分析:

  1. 程序运行后给定输出的文件路径
  2. 调用 avcodec_find_encoder 查找编码器 AVCodec
  3. 调用 avcodec_alloc_context3 分配编码器上下文 AVCodecContext
  4. 调用 av_packet_alloc 分配 AVPacket,编码器会将每个AVFrame编码为AVPacket
  5. 给 AVCodecContext 配置参数,如码率、视频宽高、帧格式等等
  6. 调用 avcodec_open2 打开编码器
  7. 调用 av_frame_alloc 分配 AVFrame 内存并设置帧的格式和宽高
  8. 调用 av_frame_get_buffer 分配帧数据使用的空间
  9. 开始for循环,首先调用 av_frame_make_writable 确保帧数据 AVFrame 可写,然后准备一帧虚拟图像数据写入 frame->data ,最后给每帧的pts赋值,告诉播放器在什么时候显示这一帧数据
  10. 开始编码,调用 avcodec_send_frame 把帧数据 AVFrame 发送给编码器
  11. 调用 avcodec_receive_packet 把编码后的帧 AVPacket 从编码器取出,然后把编码后的每一帧写入输出文件 File ,写完后调用 av_packet_unref 解除对 AVPacket 的引用
  12. 如果编码器ID是MPEG,需要向输出文件 File 的结尾添加一个固定序列从而得到一个真正的MPEG文件
  13. 最后关闭文件 File,并释放 AVCodecContext、AVFrame、AVPacket 占用的内存,调用 avcodec_free_contextav_frame_freeav_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初次学习(仅针对编码)相关推荐

  1. 使用FFMPEG——4.2.2版本实现提取视频编码解码文件,ffmpeg基础学习。

    FFMPEG基础学习 视频解码,并且输出到文件. 我通过雷霄骅的博客学习FFMPEG,在学习过程中发现"雷神"的代码由于版本的问题,很多代码已经无法在FFMPEG--4.2.2版本 ...

  2. FFmpeg再学习 -- FFmpeg解码知识

    继续看雷霄骅的 课程资料 - 基于FFmpeg+SDL的视频播放器的制作 前面用了五个篇幅来讲 FFmpeg,其主要目的是为实现将图片转视频的功能. 总的来说,对于 FFmepg 多少有一些了解了.但 ...

  3. mp4v2再学习 -- H264视频编码成MP4文件

    一.H264视频编码成MP4文件 参看:H264视频编码成MP4文件 参看:mp4v2在VS2010下的编译与在项目中的使用 最近做项目需要将H264文件封装为mp4文件,从网上找到了MP4V2库,下 ...

  4. FFmpeg深度学习模块的历史、现状和计划

    本文来自英特尔资深图形图像软件工程师 郭叶军在LiveVideoStack线上分享的内容,详细介绍了FFmpeg中深度学习模块的历史.现状及未来计划,并针对深度学习模块总体架构与代码实践做详细解析. ...

  5. FFmpeg再学习 -- 硬件加速编解码

    为了搞硬件加速编解码,用了一周时间来看 CUDA,接下来开始加以总结. 一.什么是 CUDA (1)首先需要了解一下,什么是 CUDA. 参看:百度百科 -- CUDA 参看:CUDA基础介绍 参看: ...

  6. FFmpeg再学习 -- Windows下安装说明

    看了半晌 雷霄骅 的 ffmpeg 的视频.待续稍后总结. 一.FFmpeg 简介 FFmpeg 是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用 LGPL 或GPL 许可证(依据你选择的组 ...

  7. 最简单的基于FFMPEG的视频编码器(YUV编码为H.264)

    ===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...

  8. 【LiveVideoStack线上分享】FFmpeg深度学习模块架构与代码实践

    FFmpeg可谓是音视频开发中的一把瑞士军刀,其中filter提供了很多音视频特效与图像处理的功能,除了传统的FFmpeg+OpenGL/OpenCV以外,深度学习模块提供了一种新的方式.本周四晚19 ...

  9. 深度学习赋能视频编码

    深度学习赋予了诸如计算机视觉等领域新的研究契机,其应用也获得了视频编码领域的诸多关注.在LiveVideoStack线上分享中北京大学信息技术学院 助理研究员王苫社详细介绍了当下深度学习在视频编码中的 ...

最新文章

  1. linux 逻辑卷扩展
  2. WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换
  3. Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round) A. Basic Diplomacy
  4. javascript 运算符优先级
  5. win10 安装mysql 8.0.12
  6. 五子棋的禁手c++语言实现,C++实现简单五子棋游戏
  7. UIKit框架类层次图
  8. Maven配置文件无法被导出或者生效的问题【已解决】
  9. python复杂网络库networkx:基础
  10. php单例模式的实现方式,PHP之单例模式的实现
  11. 电脑必备必装的软件工具神器,强烈推荐
  12. undo和redo日志
  13. 报道|香港科大校友“盐马行”活动成功举办
  14. 数据结构严蔚敏--综述
  15. 【嵌入式系统】STM32时钟系统+时钟配置函数解析
  16. protel 二极管正负极怎么看
  17. R语言绘图:条形图——barplot
  18. winsock和winsock2冲突
  19. html5侧匡下拉注释,可圈可点网资料
  20. CANoe软件之离线数据分析

热门文章

  1. (一)计算机视觉 --图像处理基础
  2. ubuntu chinese letter 屏幕跟读器
  3. Up or Down? Adaptive Rounding for Post-Training Quantization(记录)
  4. 大数据面试题V1.0
  5. 仅仅实用就可以了?京东家电告诉你颜值跟性能其实可以并存
  6. 阿里云Linux镜像站
  7. 20230223华清远见作业
  8. TCP接收端优化吞吐性能的把戏
  9. 聚焦信创 GBASE南大通用加入PK体系生态联盟
  10. nginx 压缩json