【音视频开发】第五章 FFmpeg基础

【音视频开发】第五章 FFmpeg基础

文章目录

一、播放器框架

1.媒体文件读取阶段

  1. 媒体文件(输入)
    通过 avformat_alloc_context() 和 avformat_open_input() 创建和打开输入文件,生成 AVFormatContext
  2. 解复用器(音视频解封装)
    使用 av_read_frame() 从媒体流中读取数据包(AVPacket),根据 AVStream 区分音频或视频数据

2.音频处理流程

  • 音频包队列(Packet Queue)
    接收音频AVPacket
  • 音频解码
    使用 avcodec_send_packet() 送入解码器,avcodec_receive_frame() 获取 AVFrame,即解码后的音频帧
  • 采样帧队列(Frame Queue)
    将音频帧缓存用于后续播放
  • 音频处理
    包括重采样、音量调节等,最终送入扬声器播放

3.视频处理流程

  • 视频包队列(Packet Queue)
    接收视频 AVPacket
  • 视频解码
    同样使用 avcodec_send_packet() 和 avcodec_recceive_frame() 获取视频帧
  • 图像帧队列(Frame Queue)
    存储待显示的图像帧
  • 图像处理
    包括格式转换、缩放、显示等,最终在显示器上播放

二、常用音视频概念

1.常用音视频术语

  • 容器/文件(Container/File):即特定格式的多媒体文件,比如 mp4、flv、mkv 等
  • 媒体流(Stream):表示时间轴上的一段连续数据,如一段声音数据、一段视频数据或一段字幕数据,可以是压缩的,也可以是非压缩的,压缩的数据需要关联特定的编解码器(有些码流音频是纯 PCM)
  • 数据帧/数据包(Frame/Packet):通常,一个媒体流是由大量的数据帧组成的,对于压缩数据,帧对应着编解码器的最小处理单元,分属于不同媒体流的数据帧交错存储于容器之中
  • 编解码器:编解码器是以帧为单位实现压缩数据和原始数据之间的相互转换的

2.复用器

"复用器"这个词,英文是 Multiplexer(简称 Mux),在音视频处理中是一个非常关键的概念,和"解复用器"(Demuxer)是相对的。

复用器的作用是把多个独立的音视频流、字幕流、元信息等数据,打包成一个统一的媒体文件格式,比如 .mp4、.mkv、.ts 等,把音频、视频、字幕合并打包成一个完整的视频文件,这个过程就叫复用。

假设有两段数据:

  • 一段是 .aac 音频
  • 一段是 .h264 视频

你想把它们合成一个 .mp4 文件,可以通过复用器完成

在 FFmpeg 命令行中就是:

bash 复制代码
ffmpeg -i video.h264 -i audio.aac -c copy output.mp4

这条命令里,-c copy 表示不重新编码,直接复用音视频流

3.编解码器

"编解码器"是音视频领域最核心的概念之一,英文叫 Codec,是 "编码器(Encoder)" 和 "解码器(Decoder)" 的合称。

  • 编码器:把原始的音视频数据压缩,变成更小、更易传输的格式(比如 H.264,AAC)
  • 解码器:把压缩后的数据还原为可播放的原始数据

拿手机拍了一个视频,这个过程可能涉及:

  • 摄像头捕获的是"原始图像数据"(未压缩,体积很大)
  • 编码器将图像压缩为 H.264 格式的视频流,生成 .mp4 文件
  • 播放这个 .mp4 文件时,解码器会把 H.264 解码为图像帧显示出来

常见编解码器

三、FFmpeg 库

1.整体结构


上层工具(命令行工具)

  • ffmpeg:核心命令行工具,用于转码、提取音视频、格式转换、滤镜处理等
  • ffplay:简单播放器,基于 SDL 和 FFmpeg,可以用来测试播放
  • ffprobe:分析媒体文件的信息(码率、时长、分辨率、流信息等)

中间核心库(libav 系列)

  • libavformat:封装/解封装库(复用器/解复用器),处理媒体容器格式,比如 MP4/MKV/FLV
  • libavcodec:编解码器库,支持各种音视频编码(如 H264、AAC、MP3)
  • libavutil:工具库,提供常用的数学、时间戳、内存处理、数据结构等工具
  • libswscale:图像缩放/像素格式转换库,比如 RGB -> YUV
  • libswreasample:音频重采样库,比如立体声转单声道,变采样率
  • libavfilter:滤镜处理库,用于音视频的剪辑、旋转、叠加等复杂处理
  • libpostproc:后处理库,主要用于解码后图像增强

编解码器支持库(第三方)

这些库不属于 FFmpeg 本身,但可以被 libavcodec 调用来支持更多的格式

  • x264:最常用的 H.264 编码器(开源)
  • fdk-aac:高质量 AAC 编码器(非完全开源)
  • voaac_enc:另一种 AAC 编码器实现

模块调用关系

bash 复制代码
ffmpeg 命令
   ↓
libavformat (封装/解封装)
   ↓
libavcodec (编解码)
   ↓
调用第三方编解码器(如 x264、fdk-aac)
   ↓
libswscale / libswresample(图像、音频处理)
   ↓
libavfilter(可选滤镜)
   ↓
libavutil(提供底层支持)

如果在开发中只想播放或分析视频,常用的是 libavformat + libavcodec + libavutil

如果要处理图像、声音或添加滤镜,就会涉及 libswscale、libswresample 和 libavfilter

四、FFmpeg 常用函数

1.libavformat 封装/解封装

2.libavcodec 编解码

3.libavutil 工具函数库

4.libswscale 图像缩放、像素格式转换

5.libswresample 音频重采样

6.内存与资源释放相关

五、FFmpeg 常用结构体

1.封装/解封装相关结构体(libavformat)

  • AVFormatContext:媒体容器上下文,负责读写媒体文件(如 MP4、MKV)
  • AVInputFormat/AVOutputFormat:输入/输出格式,(解封装器/封装器)
  • AVStream:媒体流(视频、音频、字幕等)
  • AVPacket:编码后的数据包(压缩数据,如一帧 H264)

2.编解码相关结构体(libavcodec)

  • AVCodecContext:编解码上下文,保存参数、状态等
  • AVCodec:编码器或解码器对象(如 H.264、AAC)
  • AVFrame:原始数据帧(未压缩图像/音频)
  • AVPicture(旧):图像帧结构体,已被 AVFrame 替代
  • AVCodecParameters:编解码参数(音频采样率、分辨率、码率等)

六、FFmpeg 内存模型

FFmpeg 的内存模型涉及到多个模块(编解码、封装、滤镜等)中内存的分配、使用、释放策略。掌握 FFmpeg 的内存模型,有助于写出高效稳定、不泄露内存的多媒体程序。

1.FFmpeg 内存模型核心思想

FFmpeg 的内存分配分为两类:

  • 短期内存:用于存储临时数据,如 AVPacket、AVFrame,每处理一帧就释放
  • 长期内存:如 AVFormatContext、AVCodecContext,在整个生命周期内使用,最后统一释放

2.内存生命周期关系图

bash 复制代码
打开文件
 ↓
[AVFormatContext]        ← 用于封装/解封装,生命周期较长
   ↓
 [AVStream]              ← 每个轨道对应一个 AVStream
   ↓
 [AVCodecParameters]     ← 编解码参数

打开编解码器
 ↓
[AVCodecContext]         ← 主要负责一条轨道的解码
 ↓
[AVFrame] / [AVPacket]   ← 每处理一帧数据时临时分配和释放

处理结束
 ↓
手动释放所有结构体及其 buffer

3.常用结构体的内存管理方式

4.典型内存释放策略

c 复制代码
// 分配
AVFormatContext *fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, filename, NULL, NULL);

AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
avcodec_open2(codec_ctx, codec, NULL);

AVPacket *pkt = av_packet_alloc();
AVFrame *frame = av_frame_alloc();

// 使用
while(av_read_frame(fmt_ctx, pkt) >= 0){
	// 解码
	avcodec_send_packet(codec_ctx, pkt);
	avcodec_receive_frame(codec_ctx, frame);

	// 使用完后释放这帧
	av_packet_unref(pkt);
	av_frame_unref(frame);
}

// 释放资源
av_packet_free(&pkt);
av_frame_free(&frame);
avcodec_free_context(&codec_ctx);
avformat_close_input(&fmt_ctx);
相关推荐
微帧Visionular8 小时前
AI视频单帧清晰,播放时却闪烁,原因是什么?
人工智能·深度学习·音视频
辰辰观影9 小时前
Windows网盘视频播放器推荐:无广告4K HDR怎么选
音视频
2601_9668274511 小时前
电视端云盘在线播放怎么选?支持4K HDR的应用推荐
音视频
开开心心就好12 小时前
音频降噪剪辑工具,音量裁剪一键处理
运维·服务器·前端·spring·ocr·音视频·1024程序员节
zslefour15 小时前
使用ffmpeg遍历获取音频文件相关信息
ffmpeg
AI视频工具指南16 小时前
AI视频的声音和画面怎么配合?先分清谁在传递信息
人工智能·aigc·音视频
辰辰观影18 小时前
无广告播放器推荐来啦
音视频
TrueDei18 小时前
GStreamer 使用 valve 分别控制音视频流的暂停与恢复
音视频
Android系统攻城狮18 小时前
Linux FFmpeg深度解析之avcodec_parameters_from_context调用流程与实战(十六)
linux·运维·ffmpeg·音视频进阶·ffmpeg音视频·车载音视频进阶
一条破秋裤19 小时前
基于 Hi3516CV610 的立定跳远视频测量系统调研与实施方案
arm开发·音视频