FFmpeg入门指南:从零开始掌握FFmpeg
🎬 FFmpeg入门指南:从零开始掌握FFmpeg
摘要:本文全面介绍FFmpeg的核心概念、编译安装、核心数据结构及常用API,帮助开发者快速入门音视频处理领域。适合音视频开发初学者和想要系统学习FFmpeg的开发者。
📖 前言
在音视频开发领域,FFmpeg 无疑是最重要的开源框架之一。无论是短视频应用、直播平台、视频会议软件,还是视频编辑工具,背后几乎都有FFmpeg的身影。
如果你是一名音视频开发初学者,可能会被FFmpeg庞大的代码库和复杂的API所困扰。别担心!本文将从零开始,带你系统地了解FFmpeg的核心概念、安装编译、数据结构和常用API,让你快速入门音视频开发!🚀
📑 目录
一、FFmpeg简介
1.1 什么是FFmpeg
FFmpeg 既是一款音视频编解码工具,同时也是一组音视频编解码开发套件。作为编解码开发套件,它为开发者提供了丰富的音视频处理调用接口。
FFmpeg提供了多种媒体格式的封装和解封装,包括:
- ✅ 多种音视频编码
- ✅ 多种协议的流媒体
- ✅ 多种色彩格式转化
- ✅ 多种采样率转换
- ✅ 多种码率转换等
FFmpeg框架提供了多种丰富的插件模块,包含封装与解封装的插件、编码与解码的插件。
1.2 FFmpeg的基本组成
FFmpeg主要由三部分组成:
第一部分:工具 🔧
四个作用不同的工具软件:
| 工具 | 功能 |
|---|---|
| ffmpeg.exe | 音视频转码、转换器 |
| ffplay.exe | 简单的音视频播放器 |
| ffserver.exe | 流媒体服务器(已废弃,见下文说明) |
| ffprobe.exe | 简单的多媒体码流分析器 |
⚠️ 废弃说明:
ffserver在 FFmpeg 4.0 版本中被移除。官方推荐使用其他流媒体服务器替代,如 Nginx-RTMP、SRS 等。
第二部分:SDK 📦
可供开发者使用的SDK,为各个不同平台编译完成的库。这些库可以像乐高积木一样根据需要开发自己的应用程序:
| 库 | 功能 |
|---|---|
| libavcodec | 包含音视频编码器和解码器 |
| libavutil | 包含多媒体应用常用的简化编程工具,如随机数生成器、数据结构、数学函数等 |
| libavformat | 包含多种多媒体容器格式的封装、解封装工具 |
| libavfilter | 包含多媒体处理常用的滤镜功能 |
| libavdevice | 用于音视频数据采集和渲染功能的设备相关 |
| libswscale | 用于图像缩放和色彩空间和像素格式转化功能 |
| libswresample | 用于音频重采样和格式转换功能 |
第三部分:源码 💻
整个工程的源代码,无论是编译出来的可执行程序还是SDK,都由这些源代码编译而来。
重要提示:FFmpeg的源代码由C语言实现,主要在Linux平台上进行开发。FFmpeg不是一个孤立的工程,它还存在多个依赖的第三方工程来增强它自身的功能。
1.3 FFmpeg主要功能
1.3.1 视频采集功能 📹
ffmpeg视频采集功能非常强大,不仅可以采集视频采集卡或USB摄像头的图像,还可以进行屏幕录制,同时还支持以RTP方式将视频流传送给支持RTSP的流媒体服务器,支持直播应用。
1.3.2 视频格式转换功能 🔄
ffmpeg可以轻易地实现多种视频格式之间的相互转换(wma, rm, avi, mod等),例如可以将摄录下的视频avi等转成视频网站所采用的flv格式。
1.3.3 视频截图功能 📸
对于选定的视频,截取指定时间的缩略图。视频抓图,获取静态图和动态图。
💡 提示:不提倡抓gif文件,因为抓出的gif文件大而播放不流畅。
1.3.4 滤镜功能 🎨
使用ffmpeg为视频添加水印(logo)。
1.4 FFmpeg八大库介绍
1.4.1 libavutil
核心工具库,最基础模块之一,其他模块都会依赖该库做一些基本的音视频处理操作。
1.4.2 libavformat
文件格式和协议库,封装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。
1.4.3 libavcodec
编解码库,封装了Codec层。有一些codec是具备自己的License的,FFmpeg不会默认添加像libx264、FDK-AAC、Lame等库,但是FFmpeg是一个平台,可以将其他的第三方codec以插件的方式添加进来,为开发者提供统一接口。
1.4.4 libavfilter
音视频滤镜库,该模块包含了音频特效和视频特效的处理。在使用FFmpeg的API进行编解码的过程中,可以使用该模块高效地为音视频数据做特效处理。
1.4.5 libavdevice
输入输出设备库。比如需要编译出播放声音或者视频的工具ffplay,就需要确保该模块是打开的,同时也需要libsdl的预先编译,该设备模块播放声音和视频都又是使用libsdl库。
1.4.6 libswresample
用于音频重采样,可以对数字音频进行声道数、数据格式、采样率等多种基本信息的转换。
1.4.7 libswscale
该模块用于图像格式转换,可以将YUV的数据转换为RGB的数据。
1.4.8 libpostproc
该模块用于进行后期处理。当我们使用filter的时候,需要打开这个模块,filter会用到这个模块的一些基础函数。
📌 补充说明:比较老的ffmpeg还会编译出 avresample 模块,也是用于对音频原始数据进行重采样的,但是已经被废弃,推荐使用 libswresample 替代。
另外,库里还可以包含对 H.264/MPEG-4 AVC 视频编码的 X264 库,是最常用的有损视频编码器,支持 CBR、VBR 模式,可以在编码的过程中直接改变码率的设置,在直播的场景中非常适用,可以做码率自适应的功能。
二、安装与编译
2.1 Linux编译安装
2.1.1 FFmpeg下载
下载地址:http://ffmpeg.org/download.html#releases
解压:
tar xvJf ffmpeg-4.4.2.tar.xz
2.1.2 安装x264
下载x264源码:
git clone https://code.videolan.org/videolan/x264.git
进入x264目录,配置、编译、安装:
cd x264
./configure --enable-shared --disable-asm --prefix=/usr/local/x264
make
sudo make install
参数说明:
| 参数 | 说明 |
|---|---|
--enable-shared |
生成动态库 |
--prefix |
指定安装目录 |
2.1.3 编译FFmpeg
./configure \
--enable-shared \
--prefix=/usr/local/ffmpeg \
--enable-libx264 \
--enable-gpl
make
sudo make install
参数说明:
| 参数 | 说明 |
|---|---|
--enable-shared |
生成动态库 |
--prefix |
选择安装目录 |
--extra-cflags |
指定依赖的头文件位置 |
--extra-ldflags |
指定依赖的库文件位置 |
2.1.4 配置库路径
编译完成后需要配置库路径:
# 添加库路径到配置文件
echo "/usr/local/ffmpeg/lib" >> /etc/ld.so.conf
echo "/usr/local/x264/lib" >> /etc/ld.so.conf
# 更新动态链接库缓存
sudo ldconfig
2.2 GPU版本编译(可选)
前提条件:需要安装NVIDIA CUDA环境
2.2.1 安装 nv-codec-headers
git clone https://github.com/FFmpeg/nv-codec-headers.git
cd nv-codec-headers
make
sudo make install
📌 说明:nv-codec-headers 只是头文件,提供 NVENC/NVDEC 的 API 定义。
2.2.2 配置环境变量
apt install pkg-config
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH}
pkg-config --modversion ffnvcodec
CUDA_PATH=/usr/local/cuda
export ECFLAG="-fPIC"
2.2.3 编译FFmpeg(带GPU支持)
./configure \
--enable-shared \
--prefix=/usr/local/ffmpeg \
--enable-libx264 \
--enable-gpl \
--enable-cuda-sdk \
--enable-cuvid \
--enable-nvenc \
--enable-nonfree \
--enable-libnpp \
--extra-cflags="-I/usr/local/cuda/include -I/usr/local/x264/include -I/usr/local/include/ffnvcodec -fPIC" \
--extra-ldflags="-L/usr/local/cuda/lib64 -L/usr/local/x264/lib" \
--nvcc=${CUDA_PATH}/bin/nvcc
make
sudo make install
GPU相关参数说明:
| 参数 | 说明 |
|---|---|
--enable-cuda-sdk |
启用CUDA SDK支持 |
--enable-cuvid |
启用NVDEC硬件解码 |
--enable-nvenc |
启用NVENC硬件编码 |
--enable-libnpp |
启用NVIDIA图像处理库 |
三、核心数据结构
3.1 结构体层次关系
FFmpeg中主要数据结构存在包含关系:
AVFormatContext -> AVStream -> AVCodecContext -> AVCodec
其中后者是前者的数据成员。AVFormatContext 是一个贯穿始终的数据结构,很多函数都用到它作为参数,是输入输出相关信息的一个容器。
FFmpeg中的结构体可以分为几类:
| 类别 | 主要结构体 |
|---|---|
| 解协议 | URLContext等 |
| 解封装 | AVFormatContext、AVInputFormat、AVOutputFormat |
| 解码 | AVStream、AVCodecContext、AVCodec |
| 存数据 | AVFrame、AVPacket |
3.2 AVFormatContext
📌 描述
AVFormatContext 主要存储视音频封装格式中包含的信息,位于 avformat.h 中。在使用FFmpeg进行开发的时候,AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。它是FFmpeg解封装(flv,mp4,rmvb,avi)功能的结构体。
📋 常用成员
| 成员 | 说明 |
|---|---|
duration |
视频时长,以AV_TIME_BASE为单位。计算秒:duration / AV_TIME_BASE;计算毫秒:duration / (AV_TIME_BASE / 1000) |
AVInputFormat |
输入格式(播放视频时生效) |
AVOutputFormat |
输出格式(录制视频时生效) |
AVStream **streams |
流数组,包含所有音视频流信息 |
AVCodecContext |
编解码器上下文(已废弃,见下文) |
AVCodec |
编解码器信息 |
AVFrame |
编码后的帧信息 |
💡 使用提示
处理 avformat_open_input() 和 av_read_frame() 在断流时的阻塞问题,可参考:
- https://stackoverflow.com/questions/14558172/ffmpeg-av-read-frame-need-very-long-time-to-stop
- https://www.cnblogs.com/shuiche/p/11983533.html
3.3 AVStream
📌 描述
每个 AVStream 存储一个视频/音频流的相关数据。每个AVStream对应一个AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个AVCodecContext中对应一个AVCodec,包含该视频/音频对应的解码器。
📋 常用成员
| 成员 | 类型 | 说明 |
|---|---|---|
index |
int | 标识该视频/音频流 |
codec |
AVCodecContext* | 已废弃,应使用 codecpar |
codecpar |
AVCodecParameters* | 编码器参数(推荐使用) |
time_base |
AVRational | 时基,PTS*DTS转化为真正的时间 |
duration |
int64_t | 该视频/音频流长度 |
metadata |
AVDictionary* | 元数据信息 |
avg_frame_rate |
AVRational | 帧率 |
attached_pic |
AVPacket | 附带的图片(如MP3专辑封面) |
⚠️ 废弃说明:
AVStream::codec成员已在 FFmpeg 3.1 版本废弃,FFmpeg 4.0 版本移除。应使用AVStream::codecpar替代。
💡 时基转换示例
// 将duration转化为秒
double seconds = duration * ((double)time_base.num / (double)time_base.den);
3.4 AVCodecContext
📌 描述
编解码器上下文结构体,用于存储音视频编解码器的参数和状态信息。它包含了进行音视频编解码所需的各种设置和配置,如编码器类型、编码参数、解码参数、输入输出格式等。每个音视频流在编解码过程中都需要一个对应的AVCodecContext。
⚠️ 线程安全:同一个AVCodecContext只能在一个线程中使用。之前试过在线程A中
avcodec_send_packet,在线程B中avcodec_receive_frame,程序会崩溃。
📋 常用成员
| 成员 | 说明 |
|---|---|
frame_size |
音频帧中一个声道的采样数(如AAC默认为1024)。对于音频编码,每次送入编码器的采样数要等于frame_size或能被整除,否则会异常。可使用AVAudioFifo做缓冲区。 |
codec_type |
编解码器类型(AVMEDIA_TYPE_VIDEO/AUDIO) |
codec_id |
编解码器ID |
width/height |
视频宽高 |
pix_fmt |
像素格式 |
sample_rate |
音频采样率 |
channels |
音频声道数 |
3.5 AVFrame
📌 描述
AVFrame 用于存放解码后的数据,原始视频数据(YUV、RGB等)或音频数据(PCM)。该结构体位于 avcodec.h 中。
AVFrame结构体一般用于存储原始数据(即非压缩数据),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表、QP表、运动矢量表等数据。编码的时候也存储了相关的数据。
📋 常用成员
/**
* 存储原始帧数据(对视频是YUV/RGB,对音频是PCM)
* data是指针数组,元素指向视频图像的某一plane或音频中某声道的某一plane
*
* 视频存储方式:
* Packet: Y,U,V交织存储在一个plane中,如YUVYUV...,data[0]指向这个plane
* Planar: Y,U,V存储在三个plane中,data[0]->Y, data[1]->U, data[2]->V
*
* 音频存储方式:
* Packet: L,R交织存储在一个plane中,如LRLRLR...,data[0]指向这个plane
* Planar: L,R存储在两个plane中,data[0]->L, data[1]->R
*/
uint8_t *data[AV_NUM_DATA_POINTERS];
/**
* linesize是数组,data中"一行"数据的大小
* 视频中:每个元素是图像plane中一行图像的大小(字节数),有对齐要求
* 音频中:每个元素是音频plane的大小(字节数)
*/
int linesize[AV_NUM_DATA_POINTERS];
int width, height; // 视频帧宽和高
int nb_samples; // 音频帧中包含的采样数
int format; // 解码后原始数据类型(YUV420,YUV422,RGB24...)
int key_frame; // 是否是关键帧
enum AVPictureType pict_type; // 帧类型(I,B,P...)
AVRational sample_aspect_ratio; // 宽高比(16:9,4:3...)
int64_t pts; // 显示时间戳
int coded_picture_number; // 编码帧序号
int display_picture_number; // 显示帧序号
int8_t *qscale_table; // QP表
uint8_t *mbskip_table; // 跳过宏块表
int16_t (*motion_val[2])[2]; // 运动矢量表
uint32_t *mb_type; // 宏块类型表
int interlaced_frame; // 是否是隔行扫描
3.6 AVPacket
📌 描述
AVPacket 存放解码前的数据,比如H264数据。
⚠️ 内存管理:AVPacket有两块内存,一块是它本身的;另一块是它里面数据的,即data指向的内存。释放时需要分别释放,AVPacket本身的内存调用
av_packet_free()来释放,而内部的data通过引用计数来释放,当引用计数减到0的时候,其内存就释放了。
📋 常用成员
| 成员 | 类型 | 说明 |
|---|---|---|
buf |
AVBufferRef* | 引用计数,当为0时AVPacket空间将被清除 |
data |
uint8_t* | 压缩编码的数据。对于H.264,1个AVPacket的data通常对应一个NAL |
size |
int | data的大小 |
pts |
int64_t | 显示时间戳 |
dts |
int64_t | 解码时间戳 |
stream_index |
int | 标识该AVPacket所属的视频/音频流 |
opaque |
void* | 用户自定义数据。需要开启 `codec_ctx->flags |
💡 用户自定义数据说明
⚠️ 注意:尝试了各种用户自定义数据的方法(opaque、side_data、opaque_ref),这些数据通过软解码在AVFrame中都可以获取。但是使用NVIDIA硬解码时这些数据都会丢失,连AVFrame中的pkt_dts都是无效数据。目前能确认的是AVPacket中的pts与AVFrame中的pts是相同的,可以暂且拿pts作为帧的唯一标识。
四、常用API概览
4.1 解码流程对比
FFmpeg 2.x 解码流程(已废弃)❌
av_read_frame() -> avcodec_decode_video2() -> 处理AVFrame
FFmpeg 4.x+ 解码流程(推荐)✅
av_read_frame() -> avcodec_send_packet() -> avcodec_receive_frame() -> 处理AVFrame
4.2 图像处理函数
4.2.1 sws_getContext
[函数原型]
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);
[描述]
sws_getContext 和 sws_scale 是 FFmpeg libswscale 里最核心的一对函数:
sws_getContext负责"建立转换规则"sws_scale负责"按照规则进行转换"
[参数说明]
| 参数 | 说明 |
|---|---|
| srcW, srcH | 源图像的宽、高 |
| srcFormat | 源图像的像素格式 |
| dstW, dstH | 目标图像的宽、高 |
| dstFormat | 目标图像的像素格式 |
| flags | 图像拉伸算法。SWS_BICUBIC性能好;SWS_FAST_BILINEAR平衡;SWS_POINT效果差 |
| srcFilter | 源过滤器,一般填NULL |
| dstFilter | 目标过滤器,一般填NULL |
| param | 参数,一般填NULL |
4.2.2 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[]
);
[参数说明]
| 参数 | 说明 |
|---|---|
| c | SwsContext,由sws_getContext创建 |
| srcSlice[] | 源数据,即frame->data |
| srcStride[] | 源行大小,即frame->linesize |
| srcSliceY | 从哪一行开始转换,一般从0开始 |
| srcSliceH | 转换多少行,frame->height |
| dst[] | 目标数据 |
| dstStride[] | 目标图像每一行占多少字节 |
[使用示例]
// 创建转换上下文
struct SwsContext *sws_ctx = sws_getContext(
src_width, src_height, src_pix_fmt,
dst_width, dst_height, dst_pix_fmt,
SWS_BILINEAR, NULL, NULL, NULL);
// 执行转换
sws_scale(sws_ctx,
src_frame->data, src_frame->linesize,
0, src_frame->height,
dst_data, dst_linesize);
// 释放上下文
sws_freeContext(sws_ctx);
4.2.3 av_image_alloc
[函数原型]
int av_image_alloc(
uint8_t *pointers[4],
int linesizes[4],
int w, int h,
enum AVPixelFormat pix_fmt,
int align);
[描述]
主要用于为图像分配内存并初始化相关的参数。根据给定的图像宽度、高度、像素格式等信息,分配足够的内存来存储图像数据。
⚠️ 内存释放:图像使用完成后必须使用
av_freep(&pointers[0])来释放内存。
[参数说明]
| 参数 | 说明 |
|---|---|
| pointers[4] | 指针数组,包含指向图像每个平面的指针。pointers[0]对应Y平面,pointers[1]对应U平面,依此类推 |
| linesizes[4] | 整数数组,存储每个图像平面的行大小(每行字节数) |
| w | 图像的宽度(像素) |
| h | 图像的高度(像素) |
| pix_fmt | 图像的像素格式(YUV420P、RGB24等) |
| align | 缓冲区对齐的字节数,如16字节对齐 |
[返回值]
- ✅ 成功:返回所分配的总字节数
- ❌ 失败:返回负数错误代码
[使用示例]
uint8_t *data[4] = {NULL};
int linesize[4] = {0};
// 分配YUV420P格式的图像内存
int ret = av_image_alloc(data, linesize, 1920, 1080, AV_PIX_FMT_YUV420P, 16);
if (ret < 0) {
fprintf(stderr, "Could not allocate image\n");
return -1;
}
// 使用图像数据...
// data[0] 指向Y平面
// data[1] 指向U平面
// data[2] 指向V平面
// 释放内存
av_freep(&data[0]); // 释放整个内存块
4.3 其他常用函数
4.3.1 avcodec_send_packet / avcodec_receive_frame
[函数原型]
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
[描述]
FFmpeg 4.x 新版解码API,替代已废弃的 avcodec_decode_video2()。使用 avcodec_send_packet 将数据发送给解码线程进行解码,使用 avcodec_receive_frame 从解码线程中接收解码后的数据。
⚠️ 重要:这两个函数都是异步的,且一次send可能要对应多次receive。
[返回值]
avcodec_receive_frame 返回值:
| 返回值 | 说明 |
|---|---|
| 0 | 成功,返回了一帧数据 |
| AVERROR(EAGAIN) | 当前没有输出数据,需要继续输入新数据 |
| AVERROR_EOF | 解码器已完全刷新,不会再有更多输出 |
| 其他负数 | 解码错误 |
[使用示例]
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
// 发送压缩数据到解码器
ret = avcodec_send_packet(codec_ctx, &pkt);
if (ret < 0) {
fprintf(stderr, "Error sending packet for decoding\n");
break;
}
// 接收解码后的帧(可能需要多次receive)
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
break;
}
// 处理解码后的帧
process_frame(frame);
}
av_packet_unref(&pkt);
}
4.3.2 av_read_frame
[函数原型]
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
[描述]
读取码流中的音频若干帧或者视频一帧。读取成功会将数据写入到 pkt->data 中,并通过引用计数对数据进行内存管理。
[参数说明]
| 参数 | 说明 |
|---|---|
| s | 输入的AVFormatContext |
| pkt | 输出的AVPacket |
[返回值]
返回0表示读取正常。
[使用示例]
// 推荐方式:使用栈空间
AVPacket pkt;
av_init_packet(&pkt);
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
// 处理 pkt
av_packet_unref(&pkt); // 使用完必须调用
}
⚠️ 注意:
av_init_packet()在 FFmpeg 4.4 中已被废弃,可以直接使用AVPacket pkt = {0};初始化。
4.3.3 avformat_open_input / avformat_close_input
[函数原型]
int avformat_open_input(
AVFormatContext **ps,
const char *filename,
AVInputFormat *fmt,
AVDictionary **options);
void avformat_close_input(AVFormatContext **s);
[描述]
avformat_open_input:用于打开多媒体数据并获得相关信息avformat_close_input:关闭输入文件,不仅清理AVFormatContext本身的空间,还会清除其成员指针指向的空间
[参数说明]
| 参数 | 说明 |
|---|---|
| ps | AVFormatContext结构体的指针地址 |
| filename | 视音频流的URL,支持本地文件、http、rtsp |
| fmt | 强制指定AVInputFormat,一般设为NULL让FFmpeg自动检测 |
| options | 附加选项,一般设为NULL |
[使用示例]
AVFormatContext *fmt_ctx = NULL;
// 打开输入文件
if (avformat_open_input(&fmt_ctx, filename, NULL, NULL) != 0) {
fprintf(stderr, "Could not open input file\n");
return -1;
}
// 获取流信息
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not find stream info\n");
return -1;
}
// 使用完毕后关闭
avformat_close_input(&fmt_ctx);
4.3.4 av_dump_format
[函数原型]
void av_dump_format(
AVFormatContext *ic,
int index,
const char *url,
int is_output);
[描述]
打印关于输入或输出格式的详细信息,如持续时间、比特率、流、容器、元数据、编解码器和时基。
[参数说明]
| 参数 | 说明 |
|---|---|
| ic | AVFormatContext |
| index | 用户自定义index,对打印结果无影响 |
| url | 用户自定义url,对打印结果无影响 |
| is_output | 0表示输入流,1表示输出流 |
4.4 废弃API汇总 📋
| 废弃API | 替代API | 废弃版本 | 移除版本 |
|---|---|---|---|
av_register_all() |
不再需要调用 | 4.0 | 4.0 |
avcodec_decode_video2() |
avcodec_send_packet() + avcodec_receive_frame() |
3.1 | 4.0 |
avcodec_encode_video2() |
avcodec_send_frame() + avcodec_receive_packet() |
3.1 | 4.0 |
avpicture_fill() |
av_image_fill_arrays() |
3.0 | 4.0 |
avpicture_alloc() |
av_image_alloc() |
3.0 | 4.0 |
avpicture_free() |
av_freep(&pointers[0]) |
3.0 | 4.0 |
av_init_packet() |
直接初始化 AVPacket pkt = {0}; |
4.4 | - |
AVStream::codec |
AVStream::codecpar |
3.1 | 4.0 |
ffserver |
Nginx-RTMP, SRS 等替代 | 4.0 | 4.0 |
📚 参考资料
- FFmpeg官方文档
- FFmpeg编译安装 - CentOS
- Ubuntu编译安装FFmpeg+libx264
- 雷神FFmpeg教程
- FFmpeg结构体关系
- FFmpeg函数介绍
- FFmpeg GPU编译参考
- AVPacket详解
- AVFrame详解
写在最后
FFmpeg是音视频开发的基石,掌握它需要时间和实践。本文只是入门指南,更多精彩等待你去探索!
💡 小贴士:学习过程中遇到问题,多查阅官方文档和社区资源。FFmpeg社区活跃,很多问题都能找到解决方案。
如果本文对你有帮助,欢迎点赞、收藏、评论!有问题也欢迎留言讨论~ 👋
版权声明:本文整合自多篇技术笔记,仅供学习交流使用。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)