嵌入式音视频开发——FFmpeg入门
FFmpeg 是一款功能强大且广泛使用的开源多媒体处理框架,主要用于处理音视频数据,包括转码、剪辑、合并、推流等操作。FFmpeg 的功能建立在一系列分工明确的核心库之上。为了更直观地理解它们如何协同工作,我准备了一张流程图,展示了处理媒体文件时这些库的典型协作关系:
上述流程展示了各库如何协作。
📊 核心组件库详解
库名称 | 主要功能 | 重要数据结构/API | 常见应用场景 |
---|---|---|---|
libavformat | 处理多媒体文件的封装格式(容器,如MP4、MKV、FLV)和流媒体协议(如RTMP、RTSP、HLS)。负责解封装(Demuxing)和封装(Muxing)。 | AVFormatContext , AVInputFormat , AVOutputFormat , avformat_open_input() , av_read_frame() , avformat_write_header() | 读取本地文件或网络流、视频转封装(如MKV转MP4)、流媒体推送/拉流。 |
libavcodec | 提供丰富的编解码器(Codec),用于对音视频数据进行编码(压缩)和解码(解压缩),支持H.264、H.265、AAC、MP3等众多编解码标准。 | AVCodecContext , AVCodec , AVPacket , AVFrame , avcodec_send_packet() , avcodec_receive_frame() | 视频转码(如H.264转H.265)、提取音频、视频播放器的解码核心。 |
libavfilter | 支持通过滤镜(Filter)对音视频流进行复杂处理,如缩放、裁剪、叠加水印、降噪、变速等,并可组合成滤镜图(Filtergraph)。 | AVFilterGraph , AVFilterContext , AVFilter , avfilter_graph_create_filter() , av_buffersrc_add_frame() , av_buffersink_get_frame() | 给视频加水印、生成画中画、音频混音或降噪、高级剪辑特效。 |
libavutil | 一个包含通用工具函数的辅助库,提供哈希、数学运算、日志、时间戳转换、内存管理等常用功能,是其他库的基础。 | AVDictionary , AVRational , av_malloc() , av_log() , av_rescale_q() | 几乎所有FFmpeg操作都会间接使用它,用于基础工具操作和数据结构。 |
libswscale | 专门用于处理视频图像缩放、色彩空间转换(如YUV与RGB互转)和像素格式转换。 | SwsContext , sws_getContext() , sws_scale() | 调整视频分辨率、在显示前将视频帧转换为目标格式(例如OpenGL需要RGB)。 |
libswresample | 用于处理音频重采样、格式转换(如采样位数)和声道混合等操作。 | SwrContext , swr_alloc() , swr_convert() | 调整音频采样率(如44.1kHz转48kHz)、立体声转单声道、FLTP转S16。 |
libavdevice | 和多媒体设备交互的类库,使用这个库可以读取电脑(或其他设备上)的多媒体设备的数据,或输出数据到指定的多媒体设备上。 | AVInputFormat , AVOutputFormat , avdevice_register_all() | 从摄像头或麦克风采集数据、将渲染画面输出到指定窗口或屏幕。 |
libpostproc | 用于后期效果处理,主要用于提升视频质量,如去块效应(deblocking),修复编解码过程中产生的块效应。 | pp_get_context() , pp_postprocess() | 对低码率或压缩严重的视频进行后期增强,改善主观画质。 |
FFmpeg 的这些核心库就像一支分工明确的专业团队:
- libavformat 是外交官,负责与各种文件格式和网络协议打交道。
- libavcodec 是翻译官,负责编码和解码,即压缩和解压音视频数据。
- libavfilter 是特效师,负责对原始素材进行各种加工和处理。
- libavutil 是工具库,为整个团队提供各种基础支持。
- libswscale 和 libswresample 是格式转换专家,分别负责视频和音频的格式转换。
- libavdevice 是设备接口,负责与硬件设备连接。
- libpostproc 是后期处理,负责一些画质增强工作。
FFmpeg 的工作流程涉及多个核心数据结构和 API 的协同。下图是一个典型的媒体文件转码处理流程,它展示了这些结构体和函数是如何串联起来的:

📁 解复用与容器相关 (libavformat)
结构体/上下文 | 主要用途描述 | 关键成员/相关API |
---|---|---|
AVFormatContext | 媒体格式的上下文信息,是解复用/复用的核心结构,包含文件的全局信息。 | url : 文件路径或URL。 nb_streams : 流的数量。 streams : AVStream 指针数组。 duration : 文件总时长。 bit_rate : 平均比特率。 metadata : 元数据信息(如作者、标题)。 |
AVStream | 代表媒体文件中的一条流(如视频流、音频流、字幕流)。 | index : 流的索引。 codecpar : 指向 AVCodecParameters ,存储流的编解码信息(如编码类型、分辨率、采样率)。 time_base : 该流的时间基,用于时间戳转换。 duration : 该流的时长。 |
AVInputFormat (Demuxer) | 描述输入容器格式(如MP4、FLV)。 | name : 格式名称。 long_name : 格式长名称。 read_probe : 探测文件格式的函数指针。 read_header : 读取文件头的函数指针。 read_packet : 读取数据包的函数指针。 read_seek : 跳转的函数指针。 |
AVOutputFormat (Muxer) | 描述输出容器格式。 | name : 格式名称。 long_name : 格式长名称。 audio_codec : 默认的音频编解码器。 video_codec : 默认的视频编解码器。 write_header : 写入文件头的函数指针。 write_packet : 写入数据包的函数指针。 write_trailer : 写入文件尾的函数指针。 |
AVIOContext | 封装了低层I/O操作,支持文件、网络协议(如HTTP、RTMP)的读写。 | 由FFmpeg内部管理,开发者通常通过 AVFormatContext 间接使用。 |
关键API (libavformat):
avformat_open_input(&fmt_ctx, filename, NULL, NULL)
: 打开输入文件,初始化 AVFormatContext。avformat_find_stream_info(fmt_ctx, NULL)
: 读取流信息,填充 AVFormatContext中的 streams 信息。av_read_frame(fmt_ctx, &pkt)
: 读取一个数据包(AVPacket)。av_seek_frame(fmt_ctx, stream_index, timestamp, flags)
: 跳转到指定时间点。avformat_alloc_output_context2(&fmt_ctx, NULL, NULL, filename)
: 分配输出上下文,用于复用。avio_open(&fmt_ctx->pb, filename, AVIO_FLAG_WRITE)
: 打开输出文件。avformat_write_header(fmt_ctx, NULL)
: 写入文件头。av_interleaved_write_frame(fmt_ctx, &pkt)
: 写入交错的数据包(保证音视频数据正确交织)。av_write_trailer(fmt_ctx)
: 写入文件尾。avformat_close_input(&fmt_ctx)
: 关闭输入文件并释放资源。
🔧 编解码相关 (libavcodec)
结构体/上下文 | 主要用途描述 | 关键成员/相关API |
---|---|---|
AVCodecContext | 编解码器的上下文,包含编解码所需的所有参数和信息。 | codec_type : 媒体类型(视频、音频等)。 codec : 指向 AVCodec 。 bit_rate : 目标比特率。 width/height : 视频分辨率。 pix_fmt : 视频像素格式。 sample_rate : 音频采样率。 channel_layout : 音频声道布局。 sample_fmt : 音频采样格式。 time_base : 时间基。 |
AVCodec | 代表一个编解码器(如H.264编码器、AAC解码器)。 | name : 编解码器名称。 long_name : 编解码器描述名称。 type : 媒体类型。 id : 编解码器ID。 capabilities : 编解码器能力标志。 |
AVPacket | 存储压缩编码后的数据(如一个H.264 NAL单元,或一段AAC数据)。 | data : 指向数据缓冲区的指针。 size : 数据大小。 stream_index : 所属流的索引。 pts : 显示时间戳。 dts : 解码时间戳。 duration : 包持续时间。 |
AVFrame | 存储原始(未压缩)数据(如YUV视频帧,PCM音频帧)。 | data : 指向数据平面的指针数组(如Y, U, V分量)。 linesize : 每个数据平面的行大小(步长)。 width/height : 视频帧宽高。 nb_samples : 音频帧采样数。 format : 像素格式或采样格式。 pts : 显示时间戳。 sample_rate : 音频采样率。 |
关键API (libavcodec):
avcodec_find_decoder(codec_id)
/avcodec_find_encoder(codec_id)
: 根据ID查找编解码器。avcodec_alloc_context3(codec)
: 分配编解码器上下文。avcodec_parameters_to_context(dec_ctx, stream->codecpar)
: 从流中拷贝参数到编解码器上下文。avcodec_open2(codec_ctx, codec, NULL)
: 使用给定的编解码器初始化编解码器上下文。avcodec_send_packet(codec_ctx, pkt)
: 发送一个压缩数据包 (AVPacket) 给解码器。avcodec_receive_frame(codec_ctx, frame)
: 从解码器接收一个解码后的帧 (AVFrame)。avcodec_send_frame(codec_ctx, frame)
: 发送一个原始帧 (AVFrame) 给编码器。avcodec_receive_packet(codec_ctx, pkt)
: 从编码器接收一个编码后的数据包 (AVPacket)。av_packet_alloc()
,av_packet_unref()
,av_packet_free()
: 分配、释放和取消引用 AVPacket。av_frame_alloc()
,av_frame_unref()
,av_frame_free()
: 分配、释放和取消引用 AVFrame。
🎨 处理与转换相关 (libswscale, libswresample, libavfilter)
结构体/上下文 | 主要用途描述 | 关键成员/相关API |
---|---|---|
SwsContext | 视频缩放和像素格式转换的上下文(来自libswscale)。 | 通过 sws_getContext() 创建,由 sws_scale() 内部使用。 |
SwrContext | 音频重采样和格式转换的上下文(来自libswresample)。 | 通过 swr_alloc() 或 swr_alloc_set_opts() 创建,由 swr_convert() 内部使用。 |
AVFilterGraph , AVFilterContext | 滤镜图和滤镜上下文(来自libavfilter),用于构建复杂的滤镜流程。 | 用于管理滤镜链和单个滤镜实例。 |
关键API:
sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, ...)
: 获取缩放/转换上下文。sws_scale(sws_ctx, srcSlice, srcStride, srcSliceY, srcSliceH, dst, dstStride)
: 执行视频缩放或像素格式转换。swr_alloc_set_opts(...)
: 分配并设置重采样上下文。swr_init(swr_ctx)
: 初始化重采样上下文。swr_convert(swr_ctx, &out_buf, out_samples, in_buf, in_samples)
: 执行音频重采样或格式转换。avfilter_graph_alloc()
,avfilter_graph_create_filter()
,avfilter_graph_parse_ptr()
,avfilter_graph_config()
: 用于构建和配置滤镜图。
⚙️ 工具函数 (libavutil)
libavutil 提供了许多通用工具函数和宏,例如:
av_malloc()
,av_free()
: 内存分配与释放。av_log()
: 日志输出。av_rescale_q()
: 时间戳在不同时间基之间转换。av_gettime()
: 获取当前时间。
FFmpeg 也为用户提供了直接使用的命令行工具(Tools):
- ffmpeg:这是最核心的命令行工具,用于转换音视频文件格式(转码)、进行剪辑、合并、提取、添加滤镜等各种操作。
- ffplay:一个非常简单的媒体播放器,常用于快速预览媒体文件或测试。
- ffprobe:用于分析媒体文件,显示其详细的流信息(如编解码器、分辨率、码率、时长等元数据)。