文章目錄
- 🎯 你需要理解的核心結構體:
- 📦 常用函數及使用順序(以解碼為例)
- 1?? `avcodec_find_decoder()` / `avcodec_find_encoder()`
- 2?? `avcodec_alloc_context3()`
- 3?? `avcodec_parameters_to_context()`
- 4?? `avcodec_open2()`
- 5?? `avcodec_send_packet()`(解碼)
- 6?? `avcodec_receive_frame()`(解碼)
- 🔁 對于編碼流程:
- 🧹 最后清理函數
- ? 編解碼核心流程總結(解碼):
- 1. **AVFormatContext**
- 2. **AVInputFormat**
- 3. **AVStream**
- 4. **AVCodecContext**
- 5. **AVCodec**
- 6. **AVPacket**
- 7. **AVFrame**
- 典型工作流程
🎯 你需要理解的核心結構體:
結構體名 | 作用 |
---|---|
AVCodec | 表示一個具體的編解碼器(如 H264 解碼器) |
AVCodecContext | 編解碼器上下文,保存編解碼過程中的狀態和參數 |
AVCodecParameters | 存儲編碼參數,來自媒體容器(需要轉換為 AVCodecContext) |
AVPacket | 表示壓縮的數據包(來自媒體文件或編碼后) |
AVFrame | 表示解碼后的原始幀(音頻/視頻) |
📦 常用函數及使用順序(以解碼為例)
1?? avcodec_find_decoder()
/ avcodec_find_encoder()
查找指定類型的編解碼器(如 H264 解碼器)
const AVCodec *codec = avcodec_find_decoder(codec_id);
codec_id
:如AV_CODEC_ID_H264
,AV_CODEC_ID_AAC
等- 返回
AVCodec*
,如果找不到返回NULL
2?? avcodec_alloc_context3()
創建并初始化一個
AVCodecContext
,用于后續打開編解碼器。
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
3?? avcodec_parameters_to_context()
將
AVFormatContext
中的AVCodecParameters
拷貝到AVCodecContext
。
avcodec_parameters_to_context(codec_ctx, codecpar);
codecpar
來自AVFormatContext->streams[i]->codecpar
4?? avcodec_open2()
打開編解碼器,準備進行解碼或編碼。
avcodec_open2(codec_ctx, codec, NULL);
5?? avcodec_send_packet()
(解碼)
發送壓縮包(如視頻數據包)給解碼器處理。
avcodec_send_packet(codec_ctx, &pkt);
- 解碼器內部有緩存,你可能需要多次調用
receive_frame
6?? avcodec_receive_frame()
(解碼)
從解碼器中取出解碼好的幀。
ret = avcodec_receive_frame(codec_ctx, frame);
- 當返回
AVERROR(EAGAIN)
,表示還需要更多數據才能解出新幀 AVFrame
結構保存了解碼后的一幀音視頻數據(如 YUV 圖像或 PCM 音頻)
🔁 對于編碼流程:
- 創建
AVFrame
(填充原始音視頻數據) - 調用
avcodec_send_frame()
送幀進去 - 調用
avcodec_receive_packet()
取出壓縮后的AVPacket
🧹 最后清理函數
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
av_packet_unref(&packet);
(或av_packet_free()
)
? 編解碼核心流程總結(解碼):
// 1. 找到解碼器
const AVCodec *codec = avcodec_find_decoder(codec_id);// 2. 分配上下文
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);// 3. 從 AVCodecParameters 拷貝參數
avcodec_parameters_to_context(codec_ctx, codecpar);// 4. 打開解碼器
avcodec_open2(codec_ctx, codec, NULL);// 5. 循環解碼
while (av_read_frame(fmt_ctx, &pkt) >= 0) {if (pkt.stream_index == video_stream_index) {avcodec_send_packet(codec_ctx, &pkt);while (avcodec_receive_frame(codec_ctx, frame) == 0) {// 處理解碼后的 frame,比如顯示或保存}}av_packet_unref(&pkt);
}// 6. 清理資源
avcodec_free_context(&codec_ctx);
在 FFmpeg 中,處理音視頻數據的各個組件是基于不同的結構體來管理的。這里我會簡要講解一下與音視頻解復用、編碼解碼相關的結構體,重點關注 AVFormatContext
、AVInputFormat
、AVStream
、AVCodecContext
、AVCodec
、AVPacket
和 AVFrame
等。
1. AVFormatContext
AVFormatContext
是 FFmpeg 中的核心結構體之一,它表示多媒體文件的封裝格式上下文。它用于管理和存儲整個媒體文件的各種信息,如文件格式、流信息、解復用器等。它是解碼過程中最為關鍵的結構體之一。
-
字段簡介:
format_name
:媒體文件的格式名稱(例如 MP4、AVI)。pb
:指向輸入流的指針,用于讀取數據。streams
:指向AVStream
結構體的數組,表示文件中的每一個流(視頻流、音頻流等)。flags
:文件格式的標志。nb_streams
:流的數量。
AVFormatContext
用于存儲和管理與文件格式相關的上下文信息。每當你打開一個文件(通過avformat_open_input
函數),都會創建一個AVFormatContext
。
2. AVInputFormat
AVInputFormat
是一個輸入格式的抽象層,它定義了如何解復用一個媒體文件的格式。每個格式(如 MP4、AVI、MKV)都對應一個 AVInputFormat
。
-
功能:
- 用于定義如何打開、讀取和解碼媒體文件(即數據流的讀取和分割方式)。
- 它包含一組回調函數,如
read_header
(讀取文件頭)、read_packet
(讀取數據包)、close
(關閉文件)。
AVInputFormat
是 FFmpeg 在解復用過程中使用的一個接口,用于解析不同的文件格式。
3. AVStream
AVStream
表示媒體流(如視頻流或音頻流),它通常是 AVFormatContext
結構體中的一個成員。每個 AVStream
描述了一個流的所有信息,例如編碼參數、流類型等。
-
字段簡介:
codecpar
:指向AVCodecParameters
的指針,包含了流的編解碼參數。codec
:指向AVCodecContext
的指針,存儲該流的解碼上下文。time_base
:時間基準,用于表示時間戳(即時間單位)。
每個媒體文件可能包含多個流,如視頻流、音頻流、字幕流等,
AVStream
就是用來存儲這些流的信息。
4. AVCodecContext
AVCodecContext
是解碼和編碼的上下文,它包含了與特定解碼器或編碼器相關的所有信息。每個流(如視頻流、音頻流)通常都會有一個對應的 AVCodecContext
。
-
字段簡介:
codec
:指向AVCodec
的指針,表示該流的解碼器或編碼器。width
、height
:視頻流的分辨率(僅對視頻流有效)。sample_rate
:音頻流的采樣率。bit_rate
:音視頻流的比特率。
AVCodecContext
是配置編解碼器時的關鍵結構體,包含了用于解碼或編碼的參數和信息。
5. AVCodec
AVCodec
是一個解碼器或編碼器的實現結構體。FFmpeg 支持大量的視頻和音頻編碼格式,每種編碼格式都對應一個 AVCodec
實現。
-
字段簡介:
name
:解碼器或編碼器的名稱(例如 H.264、AAC)。id
:該解碼器或編碼器的唯一標識符。type
:解碼器或編碼器的類型(音頻、視頻、字幕等)。
AVCodec
是實現具體編解碼操作的核心,它提供了操作數據流的接口,如decode
和encode
函數。
6. AVPacket
AVPacket
是一個數據包,它表示了經過解復用后的數據。解復用器將文件中的媒體流拆分成多個數據包,編碼器或解碼器將這些數據包傳遞給編解碼器進行解碼或編碼。
-
字段簡介:
data
:指向數據的指針,存儲音視頻數據。size
:數據的大小(字節數)。pts
、dts
:時間戳,表示數據的呈現時間和解碼時間。
AVPacket
是傳遞音視頻數據的核心結構,通常在解碼或編碼時作為數據傳輸的載體。
7. AVFrame
AVFrame
是解碼后的幀數據結構,它存儲了音視頻解碼后的數據(例如視頻幀或音頻樣本)。
-
字段簡介:
data
:指向音視頻幀數據的指針。linesize
:每行數據的大小,用于視頻數據。width
、height
:視頻幀的分辨率。nb_samples
:音頻幀的樣本數量。
AVFrame
是音視頻數據處理的主要結構體,解碼后的視頻幀或音頻樣本通常存儲在此結構體中。
典型工作流程
- 打開文件:使用
avformat_open_input
打開媒體文件,獲取AVFormatContext
。 - 讀取頭部信息:通過
avformat_find_stream_info
獲取流的信息。 - 查找解碼器:根據流類型(視頻流或音頻流),使用
avcodec_find_decoder
查找相應的解碼器。 - 打開解碼器:使用
avcodec_open2
打開解碼器,獲得AVCodecContext
。 - 解碼數據:通過
av_read_frame
讀取每個數據包(AVPacket
),然后通過avcodec_receive_frame
解碼并存儲到AVFrame
。 - 處理解碼后的數據:解碼后的數據可以用于播放或其他操作。
這些結構體和相關的 API 是 FFmpeg 進行音視頻處理的核心部分。希望這些解釋能幫助你更好地理解 FFmpeg 的基本流程和相關結構體。