目錄
- 參考
- 概述
- rav1e API介紹
1. 參考
2. 概述
rav1e是Mozilla/Xiph開發(fā)人員和許多志愿者開發(fā)的號稱最安全、最快的AV1編碼器。它使用rust編寫,追求良好的速度、質量和可維護性。
3. rav1e API介紹
當前的API是圍繞以下4個結構和1個枚舉構建的[2]:
-
struct Frame: 未壓縮的原始視頻數(shù)據(jù)。 -
struct Packet:壓縮的視頻碼流。 -
struct Config: 編碼器的配置。 -
struct Context: 編碼器的狀態(tài)。 -
enum EncoderStatus:Context返回的fatal或者non-fatal的狀態(tài)。
3.1 Config
Config的定義如下所示。
struct Config {
enc: EncoderConfig,
threads: usize,
}
- EncoderConfig存儲所有對實際碼流有影響的設置,而線程等設置則保存在外部。
let mut enc = EncoderConfig::with_speed_preset(speed);
enc.width = w;
enc.height = h;
enc.bit_depth = 8;
let cfg = Config { enc, threads: 0 };
Config的new_context方法
let cfg = Config { enc, threads: 0 };
let ctx: Context<u8> = cfg.new_context();
- 它產(chǎn)生一個新的編碼Context。當
bit_depth為8時,可以使用優(yōu)化的u8代碼路徑,否則必須使用u16。
3.2 Context
它由Config::new_context生成,它的實現(xiàn)細節(jié)是隱藏的。
Context相關的方法可以分為基本方法(essential)、可選方法(optional)、便利方法(convenience)。
例如下面編碼API:
// Essential API
pub fn send_frame<F>(&mut self, frame: F) -> Result<(), EncoderStatus>
where F: Into<Option<Arc<Frame<T>>>>, T: Pixel;
pub fn receive_packet(&mut self) -> Result<Packet<T>, EncoderStatus>;
- 編碼器的工作原理是通過send_frame提供的每個
Frame,通過receive_packet獲取編碼生成的Packet。
下面是可選方法的示例,在某些場景下使用。
// Optional API
pub fn container_sequence_header(&mut self) -> Vec<u8>;
pub fn get_first_pass_data(&self) -> &FirstPassData;
- 根據(jù)容器格式的不同,AV1的序列頭可以存儲在extradata中。
container_sequence_header生成預先格式化的數(shù)據(jù),以方便地存儲在mkv或mp4中。 -
rav1e支持multi-pass編碼,可以通過調用get_first_pass_data獲取第一趟編碼的數(shù)據(jù)。
下面是遍歷方法的示例,對已有方法的包裝,方便使用者使用。
// Convenience shortcuts
pub fn new_frame(&self) -> Arc<Frame<T>>;
pub fn set_limit(&mut self, limit: u64);
pub fn flush(&mut self) {
-
new_frame():根據(jù)Context中的維數(shù)和像素格式信息生成一個幀。 -
flush():在功能上相當于調用send_frame(None)。 -
set_limit():在功能上相當于在limit個幀發(fā)送到編碼器后調用flush()。
3.3 工作流程
工作流程如下所示:
- 設置
- 創(chuàng)建并設置好
Config。 - 調用
Config的new_context方法生成一個Context。
- 編碼的循環(huán)
- 使用
receive_packet嘗試獲取一個Packet。 - 如果
receive_packet返回EncoderStatus::NeedMoreData,通過send_frame給Context發(fā)送一個Frame。
- 編碼結束
- 調用
flush()將編碼器中緩存的Frame編碼到最后一個Packet。 - 調用
receive_packet,直到返回EncoderStatus:: limitarrived。